JavaScript 严格模式有什么作用?
简化版
严格模式通过 "use strict" 启用,会把一些静默错误变成显式错误,禁止部分不安全语法,改变普通函数中默认 this 指向,并让代码更容易被引擎优化和维护。
详细版
严格模式常见影响:
- 禁止意外创建全局变量。
- 普通函数独立调用时,
this是undefined,不是全局对象。 - 禁止重复参数名。
- 对只读属性赋值会报错。
- 禁止
with。 eval和arguments行为更受限制。
ES Module 和 class 默认运行在严格模式下。 面试重点是能举出行为差异,而不是只说“更严格”。
完整版教学
一、严格模式的目标是减少隐式容错
早期 JavaScript 为了兼容网页,会默默接受很多危险写法。 例如变量没声明就赋值,浏览器会把它挂到全局对象上。 严格模式把这类静默问题变成错误,让 bug 更早暴露。
'use strict';
name = 'Alice'; // ReferenceError
如果没有严格模式,这行可能创建全局变量 name。
在大型项目里,1 个拼写错误就可能污染全局状态。
严格模式的价值就是尽早阻止这种错误扩散。
二、启用方式和默认严格场景
严格模式可以在脚本或函数开头写字符串字面量 "use strict"。
它必须出现在作用域最前面的指令序言位置。
ES Module 和 class 的代码默认就是严格模式。
'use strict';
function fn() {
// 这里也是严格模式
}
function localStrict() {
'use strict';
// 只影响这个函数
}
如果一个项目已经使用 ESM,很多严格模式行为天然存在。 面试被问到时,可以补一句“现代模块代码默认严格”。
三、this 默认绑定发生变化
非严格模式下,普通函数独立调用时 this 会被替换成全局对象。
严格模式下,this 保持为 undefined。
这能避免函数无意中读写全局对象。
function show() {
'use strict';
console.log(this);
}
show(); // undefined
对比表:
| 场景 | 非严格模式 | 严格模式 |
|---|---|---|
fn() 中的 this | 全局对象 | undefined |
obj.fn() 中的 this | obj | obj |
call(1) 的 this | 包装对象 | 原始值 1 |
这也是严格模式经常和 this 绑定一起考的原因。
四、赋值错误会更早暴露
严格模式会让一些失败赋值抛出错误。 例如给不可写属性赋值、给只有 getter 的属性赋值、删除不可删除属性等。 非严格模式下这些操作可能静默失败。
'use strict';
const obj = {};
Object.defineProperty(obj, 'id', {
value: 1,
writable: false
});
obj.id = 2; // TypeError
这个例子里 id 是只读属性。
严格模式下写入直接报错,开发者能立刻定位问题。
非严格模式静默失败,后面读到旧值时更难排查。
五、禁用不利于优化和理解的语法
严格模式禁止 with。
因为 with 会动态改变作用域查找,让变量到底来自哪里变得不清楚。
这会影响可读性,也会妨碍引擎做静态分析。
'use strict';
// with (obj) {
// console.log(name);
// }
执行查找可以理解成:
普通作用域:局部 -> 外层 -> 全局
with 作用域:先插入一个动态对象 -> 再继续查找
当作用域链在运行时被临时插入对象,工具和人都更难判断变量来源。
六、arguments 和参数也更规范
严格模式禁止重复参数名。
同时 arguments 和命名参数之间不再保持那种容易混淆的联动关系。
这让函数行为更可预测。
function demo(a) {
'use strict';
a = 2;
console.log(arguments[0]);
}
demo(1); // 1
记忆钩子:严格模式不是让代码变难写,而是把隐式容错改成显式失败。
在现代工程中,打包工具、模块系统和 TypeScript 都倾向于让代码运行在更严格的语义下。
七、常见误区与追问
- 误区:严格模式会让所有代码性能变快。 它主要改善语义和可优化性,不保证每段代码都更快。
- 误区:严格模式只影响变量声明。 它还影响
this、赋值错误、参数、eval、with等。 - 误区:ES Module 还需要手动写
"use strict"。 模块代码默认严格,通常不需要重复写。 - 追问:严格模式下普通函数
this是什么? 独立调用时是undefined,不会自动指向全局对象。 - 追问:为什么禁止
with?with让作用域查找动态化,不利于理解、静态分析和优化。 - 追问:严格模式下给只读属性赋值会怎样? 会抛出 TypeError,而不是静默失败。
八、加强记忆
严格模式抓四个高频点:防全局污染、this 不默认指向全局、静默失败变报错、禁用不安全语法。回答时用“未声明变量赋值”和“普通函数 this”两个例子,就能把作用讲实。