JavaScript 严格模式
JavaScript 使用严格模式 (Use Strict)
Section titled “JavaScript 使用严格模式 (Use Strict)”"use strict"; 是一条指令 (directive),用于在 JavaScript 中启用“严格模式 (strict mode)”。严格模式改变了 JavaScript 代码的执行方式,通过捕获常见的编码错误以及阻止或抛出某些“不安全”行为的错误,使其更加健壮 (robust)。
"use strict" 指令
Section titled “"use strict" 指令”"use strict" 指令是在 ECMAScript 5 (ES5) 中引入的。
它不是一个语句 (statement),而是一个字面量表达式 (literal expression)。不支持严格模式的旧版 JavaScript 引擎会简单地忽略它。
"use strict" 的目的是选择使用 JavaScript 的一个受限制的变体,通常称为“严格模式 (strict mode)”。
例如,在严格模式下,你不能使用未声明的变量,这有助于防止意外创建全局变量。
| 严格模式在所有现代浏览器(IE10+、Firefox 4+、Chrome 13+、Safari 5.1+、Opera 12+)和 Node.js 中都得到了广泛支持。 |
|---|
声明严格模式
Section titled “声明严格模式”通过在脚本或函数的开头添加 "use strict"; 来声明严格模式。
1. 全局作用域 (Global Scope)(脚本级别):
Section titled “1. 全局作用域 (Global Scope)(脚本级别):”当在脚本文件的开头声明时,严格模式适用于整个脚本。
// 在脚本文件 (例如 myscript.js) 中"use strict";
// let x = 3.14; // 没问题,因为 x 已声明// y = 3.14; // 这会引发 ReferenceError,因为 y 未声明
// function myFunction() {// // 这个函数也在严格模式下// // z = 3.14; // ReferenceError// }// myFunction();2. 函数作用域 (Function Scope)(局部):
Section titled “2. 函数作用域 (Function Scope)(局部):”当在函数体的开头声明时,严格模式仅适用于该函数内部的代码。
// x = 3.14; // 如果不在全局严格模式下,这可能是允许的,或者会创建一个全局变量
// function strictFunction() {// "use strict";// // 这个函数在严格模式下// // y = 3.14; // ReferenceError// let z = 3.14; // OK// }// strictFunction();
// function nonStrictFunction() {// // 这个函数不在严格模式下(除非整个脚本都在严格模式下)// // w = 3.14; // 可能会创建全局变量,或根据外部作用域而报错// }// nonStrictFunction();现代 JavaScript 的重要注意事项:
JavaScript 模块 (module)(在 HTML 中使用 <script type="module">,或在 Node.js 中使用 ES module 语法)自动处于严格模式。你无需在模块中添加 "use strict";。
ES6 class 内部的代码也始终处于严格模式。
为什么要使用严格模式?
Section titled “为什么要使用严格模式?”- 捕获常见编码错误: 将静默错误 (silent errors) 转变为抛出错误 (thrown errors)(例如,给未声明的变量赋值)。
- 阻止“不安全”行为: 禁止向只读的全局属性写入值或删除不可配置的属性。
- 禁用令人困惑或考虑不周的特性: 移除或改变了
with语句和带有前导零的八进制字面量等特性。 - 简化变量解析: 使开发者和 JavaScript 引擎更容易理解变量作用域。
- 增强
eval()的安全性: 在严格模式下,eval()中声明的变量和函数不会污染外部作用域。 - 改变
this的绑定: 在没有显式上下文调用的函数中(不是作为方法或构造函数调用时),this将是undefined(而非严格模式下的全局对象)。这阻止了意外修改全局变量的行为。 - 为未来的 ECMAScript 版本做准备: 禁止在未来版本中可能使用的语法(例如,某些保留字)。
严格模式下的主要变化和限制
Section titled “严格模式下的主要变化和限制”- 未声明的变量:
给未声明的变量赋值会抛出 ReferenceError 错误(防止意外创建全局变量)。
// "use strict";// undeclaredVar = 10; // ReferenceError- 删除变量、函数或实参:
对变量名、函数名或实参名使用 delete 会抛出 SyntaxError 错误。
// "use strict";// let x = 3.14;// delete x; // SyntaxError
// function myFunction(arg) {// delete arg; // SyntaxError// }// delete myFunction; // SyntaxError- 重复的属性名或参数名:
对象字面量 (object literal) 中的重复属性名或函数定义中的重复参数名会引发 SyntaxError 错误。
// "use strict";// const obj = { p1: 10, p1: 20 }; // SyntaxError// function sum(a, a) {} // SyntaxError- 八进制语法:
带有前导零的八进制数字字面量(例如,010)会引发 SyntaxError。请使用现代的 0o 前缀(例如,0o10)。字符串中的八进制转义序列(例如,"\010")也被禁止。
// "use strict";// const octalNum = 010; // SyntaxError// const octalStr = "\010"; // SyntaxError (在某些上下文)// const modernOctal = 0o10; // OK, 值为 8- 写入只读或不可写属性:
向不可写属性 (non-writable property)、只读访问器属性 (getter-only property),或不可扩展对象 (non-extensible object) 上的非现有属性赋值会抛出 TypeError 错误。
// "use strict";// const obj = {};// Object.defineProperty(obj, "x", { value: 0, writable: false });// obj.x = 3.14; // TypeError
// const obj2 = { get y() { return 0; } };// obj2.y = 3.14; // TypeError- 删除不可配置属性:
尝试 delete 不可配置属性 (non-configurable property) 会抛出 TypeError 错误。
// "use strict";// delete Object.prototype; // TypeError- 将
eval和arguments作为标识符:
字符串 eval 和 arguments 不能用作变量名、函数名、参数名或标签 (labels)。
// "use strict";// let eval = 3.14; // SyntaxError// let arguments = "test"; // SyntaxErrorwith语句:
with 语句在严格模式下是 SyntaxError。
// "use strict";// with (Math) { x = cos(2); } // SyntaxErroreval()作用域:
在 eval() 代码中声明的变量和函数不会在外部作用域中创建(它们会在 eval 调用创建一个新的作用域)。
// "use strict";// eval("let newVar = 2;");// console.log(typeof newVar); // "undefined" (newVar 不在此作用域)- 函数中的
this:
在没有特定上下文调用的函数中(例如,myFunc() 而不是 obj.myFunc() 或 new MyFunc()),this 是 undefined(而非严格模式下的全局对象)。
// "use strict";// function showThis() {// console.log(this); // undefined// }// showThis();arguments.callee和arguments.caller:
访问 arguments.callee(指向封闭函数)或 arguments.caller(指向调用封闭函数的函数)会抛出 TypeError 错误。
- 保留关键字:
将未来的保留关键字(如 implements、interface、let(尽管 let 现已实现)、package、private、protected、public、static、yield)用作变量或函数名会引发 SyntaxError。这有助于确保向未来 JavaScript 版本的平滑过渡。
"use strict"; 指令只能在脚本或函数体的最开头被识别。在其前面不能有任何其他语句(注释或其他指令除外)。 |
|---|
强烈建议所有新的 JavaScript 项目都使用严格模式,以编写更清晰、更可靠、更安全的代码。