跳到主要内容

JavaScript 严格模式

在JavaScript的发展过程中,为了保持对老代码的兼容性,许多早期的设计缺陷和不严谨的特性一直被保留下来。然而,这些特性可能导致代码中出现隐蔽的错误或安全问题。为了解决这个问题,ECMAScript 5 引入了"严格模式"(Strict Mode),它是一种特殊的执行模式,让JavaScript代码运行在更严格的环境中。

什么是严格模式?

严格模式是JavaScript的一种受限制的变体,它故意与普通JavaScript有所不同。严格模式通过以下方式改变JavaScript的语义:

  1. 将一些JavaScript静默错误转为明显的异常
  2. 修复了一些导致JavaScript引擎难以优化的缺陷
  3. 禁用了一些在未来ECMAScript版本中可能被定义的语法

如何启用严格模式

有两种方式可以启用严格模式:

1. 脚本级严格模式

在脚本的最顶部添加 "use strict"'use strict' 声明,整个脚本将以严格模式执行:

javascript
"use strict";
// 以下代码将在严格模式下执行
var x = 10;
console.log(x); // 10

2. 函数级严格模式

在函数体的开头添加 "use strict" 声明,只有该函数内的代码会在严格模式下执行:

javascript
function strictFunction() {
"use strict";
// 此函数内的代码在严格模式下执行
return "I'm in strict mode";
}

function normalFunction() {
// 此函数在非严格模式下执行
return "I'm in normal mode";
}

console.log(strictFunction()); // "I'm in strict mode"
console.log(normalFunction()); // "I'm in normal mode"
注意

不要在代码中间启用严格模式,这样做可能导致不可预测的行为。严格模式声明应该始终出现在脚本或函数的开头。

严格模式的主要限制和变化

1. 禁止使用未声明的变量

在非严格模式下,如果你不小心漏掉了 varletconst 声明,JavaScript 会创建一个全局变量:

javascript
// 非严格模式
function nonStrict() {
x = 10; // 没有声明就使用x
console.log(x); // 10
}
nonStrict();
console.log(x); // 10 (x成为了全局变量)

而在严格模式下:

javascript
// 严格模式
function strict() {
"use strict";
x = 10; // 未声明变量
console.log(x);
}
// 运行结果: ReferenceError: x is not defined

2. 禁止删除变量、函数和不可删除的属性

javascript
"use strict";
var x = 10;
delete x; // SyntaxError

function y() {}
delete y; // SyntaxError

delete Object.prototype; // TypeError

3. 函数参数必须唯一

在非严格模式下,重复的函数参数会默认使用最后一个参数值。而在严格模式下,这将导致语法错误:

javascript
// 非严格模式
function sum(a, a, c) {
return a + a + c; // 这里的a是第二个a参数
}
console.log(sum(1, 2, 3)); // 7 (2+2+3)

// 严格模式
"use strict";
function sum(a, a, c) { // SyntaxError: Duplicate parameter name not allowed in this context
return a + a + c;
}

4. this 的值不会默认转为对象

在非严格模式下,当 this 指向原始值时,会被自动转换为对象:

javascript
// 非严格模式
function showThis() {
console.log(typeof this);
}

showThis(); // "object" (this指向window)
showThis.call(5); // "object" (this是Number对象)

在严格模式下,this 将保持原始值:

javascript
// 严格模式
"use strict";
function showThis() {
console.log(typeof this);
}

showThis(); // "undefined"
showThis.call(5); // "number"

5. 禁止八进制语法

在严格模式下,八进制语法被禁止使用:

javascript
// 非严格模式
var num = 010; // 8 (八进制)
console.log(num); // 8

// 严格模式
"use strict";
var num = 010; // SyntaxError: Octal literals are not allowed in strict mode.
备注

现代JavaScript支持新的八进制表示法,即使在严格模式下也可以使用:var num = 0o10;

6. 禁止在普通函数中设置 argumentseval

javascript
"use strict";
var arguments = 10; // SyntaxError
var eval = 20; // SyntaxError

7. 禁止使用 with 语句

javascript
"use strict";
var obj = { x: 10 };
with(obj) { // SyntaxError: Strict mode code may not include a with statement
x = 20;
}

真实应用场景

1. 在大型项目中捕获错误

想象你正在维护一个大型JavaScript应用程序,严格模式可以帮助你在开发阶段发现潜在问题:

javascript
"use strict";

function processUserData(userData) {
// 假设忘记声明变量
userId = userData.id; // 立即抛出错误,而不是创建全局变量

// 其他处理...
}

// 使用严格模式,问题会在测试阶段被发现
// 而不是在生产环境中造成难以追踪的bug

2. 模块开发中的安全保障

当你开发可重用的JavaScript库或模块时,严格模式可以防止你的代码意外污染全局命名空间:

javascript
(function() {
"use strict";

// 库的所有代码都在严格模式下运行
function MyLibrary() {
// 库的实现...
}

// 导出到全局对象
window.MyLibrary = MyLibrary;
})();

3. ES6模块中的自动严格模式

值得注意的是,在使用ES6模块系统时,所有代码默认都在严格模式下运行,无需显式声明:

javascript
// 这个文件以 .js 或 .mjs 扩展名导入/导出模块
// 默认在严格模式下运行

export function myFunction() {
// 已经在严格模式下,不需要"use strict"
undeclaredVar = 5; // 这将抛出错误
}

严格模式的优势

  1. 更少的错误:通过将隐藏的错误转换为明显的异常,帮助你更早地发现问题。

  2. 更安全的代码:防止意外创建全局变量,限制潜在的安全风险。

  3. 更好的性能:一些严格模式的限制使JavaScript引擎能够执行更多的优化。

  4. 为未来做准备:避免使用可能在未来版本中被废弃的功能。

何时使用严格模式

建议在以下情况使用严格模式:

  • 所有新的JavaScript项目
  • 模块化的代码
  • 当你需要确保代码质量和可靠性时

对于现有的大型项目,可以逐步引入严格模式,比如只在新的函数或模块中启用它,而不是一次性转换所有代码。

总结

JavaScript严格模式是提高代码质量和安全性的重要工具。它通过强制更严格的语法规则、禁用一些不安全的特性,以及改变一些JavaScript行为来帮助开发者编写更好的代码。虽然它可能需要一些时间来适应,但长期来看,它会帮助你避免许多常见的JavaScript陷阱和错误。

在现代JavaScript开发中,使用严格模式已经成为最佳实践,特别是当你使用ES6模块系统时,它已经是默认行为。掌握严格模式的规则和限制,将帮助你成为一个更专业的JavaScript开发者。

练习

  1. 尝试编写一个在严格模式下会抛出错误,但在非严格模式下能正常运行的函数。
  2. 创建一个项目,在一些函数中使用严格模式,在其他函数中不使用,观察有什么不同。
  3. 查找现有代码库中可能会被严格模式捕获的潜在问题。

其他资源

通过学习和应用严格模式,你将能够编写更健壮、更安全的JavaScript代码。