JavaScript 严格模式

124 阅读2分钟

它是什么

给 JS 开个“较真模式”。一旦开启,JavaScript 会对一些原本“容忍/默默忽略”的危险写法直接抛错或改变行为,从而更早暴露 bug、更安全、更利于引擎优化。

为什么有意义

  • 更早发现错误:很多隐性 bug 当场报错,缩短排查时间。
  • 更安全:禁掉易被利用或难以理解的语法(如 witharguments.callee)。
  • 更一致:减少不同引擎下的歧义和历史包袱。
  • 更好优化:明确语义后,JS 引擎更容易做性能优化。

怎么开启

  • 在脚本或函数第一行写:"use strict";
  • ES6+ 模块与类默认就是严格模式;打包后的现代项目通常已经处于严格模式(多半不用手写这句)。

具体有什么变化(高频清单 + 例子)

  1. 禁止意外创建全局变量
"use strict";
function f() { x = 1 } // ReferenceError:x 未声明

(非严格下会悄悄变成 window.x

  1. 普通函数里的 this 不再自动指向全局
function f(){ return this }
f(); // 非严格: window/global;严格: undefined
  1. 参数名不能重复
function sum(a, a) {} // 严格: SyntaxError
  1. eval 变“隔离” (不再向外层注入变量)
"use strict";
eval("var x = 1;");
typeof x; // "undefined"
  1. 不能删除变量/函数/参数
"use strict";
var x = 1;
delete x; // SyntaxError
  1. 写入只读属性会抛错(非严格下静默失败)
"use strict";
const obj = {};
Object.defineProperty(obj, "id", { value: 1, writable: false });
obj.id = 2; // TypeError
  1. 禁用 with
"use strict";
with (obj) {} // SyntaxError
  1. 八进制字面量与转义受限
"use strict";
var n = 010; // SyntaxError(非严格下表示八进制 8)
  1. arguments 行为更“干净”
  • 不再和形参联动(改 arguments[0] 不会改到形参)。
  • 禁用 arguments.callee/arguments.caller(TypeError)。
  • 不能给 eval/arguments 赋值或作为变量名。
  1. 保留字更严格
    publicstatic(以及未来关键字)在严格模式下不可作为变量名。

什么时候我“已经在严格模式”?

  • 你用 ES modules (import/export)class:默认严格。
  • 现代打包工具(Webpack、Vite、Rollup)产物通常已严格。
  • 旧式 IIFE/脚本直连时,若没模块化,才可能需要手写 "use strict"

实战建议

  • 新项目/模块化项目:基本天然严格,无需额外处理。
  • 维护旧代码:可以按“文件或函数”为单位逐步加 "use strict",配合 eslint,把上面这些典型坑扫一遍。
  • 库作者:保持严格模式有助于用户环境一致性与可优化性。