Skip to content

JavaScript 严格模式

JavaScript 使用严格模式 (Use Strict)

Section titled “JavaScript 使用严格模式 (Use Strict)”

"use strict"; 是一条指令 (directive),用于在 JavaScript 中启用“严格模式 (strict mode)”。严格模式改变了 JavaScript 代码的执行方式,通过捕获常见的编码错误以及阻止或抛出某些“不安全”行为的错误,使其更加健壮 (robust)。

"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 中都得到了广泛支持。

通过在脚本或函数的开头添加 "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 内部的代码也始终处于严格模式。

  • 捕获常见编码错误: 将静默错误 (silent errors) 转变为抛出错误 (thrown errors)(例如,给未声明的变量赋值)。
  • 阻止“不安全”行为: 禁止向只读的全局属性写入值或删除不可配置的属性。
  • 禁用令人困惑或考虑不周的特性: 移除或改变了 with 语句和带有前导零的八进制字面量等特性。
  • 简化变量解析: 使开发者和 JavaScript 引擎更容易理解变量作用域。
  • 增强 eval() 的安全性: 在严格模式下,eval() 中声明的变量和函数不会污染外部作用域。
  • 改变 this 的绑定: 在没有显式上下文调用的函数中(不是作为方法或构造函数调用时),this 将是 undefined(而非严格模式下的全局对象)。这阻止了意外修改全局变量的行为。
  • 为未来的 ECMAScript 版本做准备: 禁止在未来版本中可能使用的语法(例如,某些保留字)。
  1. 未声明的变量:

给未声明的变量赋值会抛出 ReferenceError 错误(防止意外创建全局变量)。

// "use strict";
// undeclaredVar = 10; // ReferenceError
  1. 删除变量、函数或实参:

对变量名、函数名或实参名使用 delete 会抛出 SyntaxError 错误。

// "use strict";
// let x = 3.14;
// delete x; // SyntaxError
// function myFunction(arg) {
// delete arg; // SyntaxError
// }
// delete myFunction; // SyntaxError
  1. 重复的属性名或参数名:

对象字面量 (object literal) 中的重复属性名或函数定义中的重复参数名会引发 SyntaxError 错误。

// "use strict";
// const obj = { p1: 10, p1: 20 }; // SyntaxError
// function sum(a, a) {} // SyntaxError
  1. 八进制语法:

带有前导零的八进制数字字面量(例如,010)会引发 SyntaxError。请使用现代的 0o 前缀(例如,0o10)。字符串中的八进制转义序列(例如,"\010")也被禁止。

// "use strict";
// const octalNum = 010; // SyntaxError
// const octalStr = "\010"; // SyntaxError (在某些上下文)
// const modernOctal = 0o10; // OK, 值为 8
  1. 写入只读或不可写属性:

向不可写属性 (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
  1. 删除不可配置属性:

尝试 delete 不可配置属性 (non-configurable property) 会抛出 TypeError 错误。

// "use strict";
// delete Object.prototype; // TypeError
  1. 将 eval 和 arguments 作为标识符:

字符串 eval 和 arguments 不能用作变量名、函数名、参数名或标签 (labels)。

// "use strict";
// let eval = 3.14; // SyntaxError
// let arguments = "test"; // SyntaxError
  1. with 语句:

with 语句在严格模式下是 SyntaxError。

// "use strict";
// with (Math) { x = cos(2); } // SyntaxError
  1. eval() 作用域:

在 eval() 代码中声明的变量和函数不会在外部作用域中创建(它们会在 eval 调用创建一个新的作用域)。

// "use strict";
// eval("let newVar = 2;");
// console.log(typeof newVar); // "undefined" (newVar 不在此作用域)
  1. 函数中的 this:

在没有特定上下文调用的函数中(例如,myFunc() 而不是 obj.myFunc() 或 new MyFunc()),this 是 undefined(而非严格模式下的全局对象)。

// "use strict";
// function showThis() {
// console.log(this); // undefined
// }
// showThis();
  1. arguments.callee 和 arguments.caller:

访问 arguments.callee(指向封闭函数)或 arguments.caller(指向调用封闭函数的函数)会抛出 TypeError 错误。

  1. 保留关键字:

将未来的保留关键字(如 implements、interface、let(尽管 let 现已实现)、package、private、protected、public、static、yield)用作变量或函数名会引发 SyntaxError。这有助于确保向未来 JavaScript 版本的平滑过渡。

"use strict"; 指令只能在脚本或函数体的最开头被识别。在其前面不能有任何其他语句(注释或其他指令除外)。

强烈建议所有新的 JavaScript 项目都使用严格模式,以编写更清晰、更可靠、更安全的代码。