人人都会AI编程

2.5 严格模式:开启方式、作用与约束规则

更新时间:2026-07-11

JavaScript 在早期为了降低上手门槛,设计得过于宽容,很多“静默失败”或容易引发 bug 的写法在当时都被允许。随着语言规模的膨胀,这些历史设计缺陷越来越成为工程化的绊脚石。ES5 引入了严格模式(Strict Mode),允许开发者选择一种更规范、更安全的运行方式。严格模式并不是一门新语言,而是 JavaScript 的一个“安全模式”开关。

2.5.1 开启方式

严格模式的开启非常简单,只需要在作用域顶端加一行字符串 'use strict'"use strict" 即可。它的作用范围取决于你把这行声明放在哪里。

全局开启
在脚本文件(或 <script> 标签)最顶端添加严格模式声明,整个脚本都在严格模式下运行。注意,多个 <script> 标签之间是独立的,在一个标签中开启不会影响另一个。

<script>
"use strict";
// 现在所有代码都在严格模式下执行
var x = 3.14;
</script>

函数级开启
在函数体内部最顶端添加声明,只让该函数内部进入严格模式。这在只有部分代码需要严格检查、或者你无法控制整个脚本时特别有用。

function doSomething() {
  "use strict";
  // 在这个函数内是严格模式
}
// 函数外部仍然是普通模式

模块与类自动严格
ES6 引入的 class 和模块系统(import / export默认自动严格模式,你不需要显式添加 "use strict" 声明。Node.js 中,.mjs 文件或项目 package.json 中配置 "type": "module" 后,所有模块也自动严格。

一个常见陷阱
"use strict" 必须写在作用域的最顶端,中间不能有其他实际语句(注释除外),否则会被忽略。

// 错误:前面有代码
var x = 1;
"use strict"; // 无效!会被当作普通字符串

2.5.2 严格模式的作用

严格模式的核心目标可以概括为三点:

  1. 消除 JavaScript 中一些不合理、不严谨的语法,减少怪异行为。将之前“默默失败”的错误变成显式抛出异常,让 bug 尽早暴露。
  2. 修复一些阻碍引擎优化的缺陷,提升代码执行效率。比如禁用了 with 语句,消除了变量查找中的不确定性,让引擎优化变得更加安全。
  3. 为未来新版本的 JavaScript 铺路,预留关键字。禁止将一些可能在未来成为关键字的词用作变量名。

简单说,严格模式让 JavaScript 变得更“现代”,帮助开发者写出更健壮、更容易维护的代码。大多数现代工程都会开启严格模式,ESLint 等工具也强烈推荐启用。

2.5.3 主要约束规则

严格模式下的限制覆盖了变量访问、作用域、函数调用、对象操作等多个方面。以下是开发者最常遇到、也最重要的规则:

一、变量必须声明

在普通模式下,直接给未声明的变量赋值会自动创建一个全局变量(隐式全局提升),这是导致命名污染和难以排查 bug 的元凶之一。严格模式下,这种行为会直接抛出 ReferenceError

"use strict";
x = 10; // ReferenceError: x is not defined

二、禁止删除变量和不可删除的属性

在普通模式下,delete 运算符用于变量或某些不可配置属性时会静默返回 false。严格模式下,直接抛出 SyntaxErrorTypeError

"use strict";
var y = 20;
delete y; // SyntaxError: 不能删除变量

var obj = {};
Object.defineProperty(obj, "prop", { value: 1, configurable: false });
delete obj.prop; // TypeError:不能删除不可配置属性

三、函数的参数名必须唯一

普通模式下,如果定义函数时使用了重复的参数名,后面的参数会覆盖前面的,不报错。严格模式下直接抛出语法错误。

function sum(a, a, c) {  // 严格模式下 SyntaxError
  "use strict";
  return a + c;
}

四、禁止八进制数字字面量

普通模式下,以 0 开头的数字可能被解释为八进制(如 012 代表十进制的 10),这容易造成混淆。严格模式下,直接用 0 前缀(不带 o)的写法会报错,必须使用 0o0O(ES6 标准写法)。

"use strict";
var num = 0755; // SyntaxError
var num = 0o755; // 正确,八进制写法

五、evalarguments 限制

  • 不能用作标识符:严格模式下,evalarguments 不能作为变量名、函数名或参数名。
  • eval 拥有自己的作用域:在普通模式下,eval("var x = 1") 会在当前作用域创建变量 x;在严格模式下,eval 中的变量只存在于 eval 内部,不会泄漏到外层作用域。
  • arguments 不再追踪参数变化:在普通模式下,修改 arguments 对象的值会反过来改变对应的参数值,反之亦然。严格模式下,arguments 只是参数的一个副本,与参数相互独立。
"use strict";
function test(a) {
  a = 2;
  console.log(arguments[0]); // 仍然是 1,不受影响
}
test(1);

六、this 值不再自动包装为对象

普通模式下,如果一个函数的 thisnullundefined,会被自动替换为全局对象(浏览器中是 window)。严格模式下,this 保持原值,不进行任何转换。这让函数调用的 this 更可预测。

"use strict";
function showThis() {
  console.log(this);
}
showThis(); // undefined(普通模式下是 window)

同样,在严格模式下通过 callapplybind 传入的原始值不会被装箱为对象。

七、禁止 with 语句

with 语句允许将某个对象添加到作用域链的头部,使代码可以直接访问该对象的属性,但会导致代码混乱、性能低下,并且引擎无法优化。严格模式下直接禁止使用 with,出现就报错。

"use strict";
with (Math) { // SyntaxError
  var x = cos(3);
}

八、保留关键字增加

为将来可能的语言扩展,严格模式新增了一些保留关键字:implementsinterfaceletpackageprivateprotectedpublicstaticyield。这些词不能作为变量名或函数名。

2.5.4 使用建议

在实际开发中,你有两个选择:

  • 全项目严格模式:所有脚本和函数顶部都加上 "use strict"。这是推荐做法,几乎所有现代框架和构建工具都默认启用严格模式。
  • 函数级严格模式:当你的代码需要与某些不兼容严格模式的旧代码混用时,只对特定函数开启严格模式,是平稳迁移的实用策略。

另外,在使用 Babel 或 TypeScript 等工具时,它们会自动处理严格模式的转换,你甚至不需要手动添加声明,但理解其规则仍然非常重要——它将影响你调试时实际看到的行为。

以后在学习和编写代码时,建议默认以严格模式思考,把它当作 JavaScript 的“正常”运行方式,这样既能避免大多数经典坑点,也为未来的代码维护打下良好基础。