JS 严格模式:从「自由散漫」到「规范严谨」的代码指南
在 JavaScript 世界里,「普通模式」像无人看管的菜市场------允许未声明变量、容忍重复参数、this
指向飘忽不定;而「严格模式」则像有规可循的写字楼,用明确规则规避潜在风险、提升代码质量。作为现代前端开发的标配,严格模式不仅是 ES5 引入的重要特性,更是 webpack 等构建工具的默认配置。今天,我们就从「是什么、做什么、为什么用、怎么用」四个维度,彻底搞懂 JS 严格模式。
一、先搞懂:严格模式到底是什么?
严格模式("use strict"
)是 JavaScript 的一种限制性执行模式 ,从 ECMAScript 5 开始引入。它的核心目标是:修复语言设计缺陷、禁止不安全操作、规范代码行为,让 JS 代码从「灵活但混乱」走向「严谨且可控」。
可以用一个生动的类比理解两种模式的差异:
- 普通模式:在家办公,穿着睡衣也能写代码,偶尔偷懒(比如不声明变量)也没人管;
- 严格模式:去公司上班,必须遵守规章制度(变量要声明、参数不重复),每一步操作都有明确规范。
启用方式也很简单,只需在代码最顶部(或函数内部顶部)添加一行字符串:
js
// 全局启用严格模式(整个脚本文件生效)
"use strict";
// 或在函数内部启用(仅该函数生效)
function strictFunc() {
"use strict";
// 函数内代码遵循严格模式
}
特别注意:ES 模块(使用 import
/export
的文件)会默认启用严格模式 ,无需手动添加 "use strict"
。
二、核心重点:严格模式到底限制了什么?
严格模式的核心价值,在于通过「禁止错误操作」提前暴露问题。下面我们逐一拆解它的关键限制,结合代码对比理解差异。
1. 禁止使用「未声明的变量」:杜绝全局污染
这是严格模式最常用的限制之一。在普通模式下,未声明的变量会自动成为全局变量(浏览器中挂载到 window
),很容易意外覆盖全局属性;而严格模式会直接报错,从源头避免全局污染。
模式 | 代码示例 | 执行结果 |
---|---|---|
普通模式 | a = 10; console.log(window.a); |
不报错,输出 10 (变量自动挂载到 window ) |
严格模式 | "use strict"; a = 10; |
直接抛出 ReferenceError: a is not defined |
生活类比:就像你不能随便占用公司公共工位放私人物品------使用变量前,必须先「声明」(申请使用权)。
2. 改变 this
指向规则:告别「飘忽不定」
this
指向是 JS 初学者的高频痛点,普通模式下「直接调用的函数中,this
指向全局对象」的设计,更是坑了无数开发者。而严格模式通过固定 this
指向逻辑,彻底解决了这个问题。
我们用「对象方法内部函数」的经典场景对比:
场景 1:全局函数中的 this
js
// 普通模式:this 指向 window(浏览器)
function nonStrictThis() {
console.log(this === window); // 输出 true
}
nonStrictThis();
// 严格模式:this 指向 undefined
"use strict";
function strictThis() {
console.log(this === undefined); // 输出 true
}
strictThis();
场景 2:对象方法的内部函数
js
const obj = {
name: "Alice",
greet: function () {
console.log("Hello " + this.name); // 这里 this 指向 obj(两种模式一致)
// 内部函数的 this 差异
function innerFunc() {
console.log("Inner this:", this);
}
innerFunc();
}
};
// 普通模式:innerFunc 中 this 指向 window(意外全局污染风险)
obj.greet(); // Inner this: Window
// 严格模式:innerFunc 中 this 指向 undefined(明确且安全)
"use strict";
obj.greet(); // Inner this: undefined
关键结论 :严格模式下,「直接调用的函数」(非对象方法、非 new
构造、非 bind/call/apply
绑定)中,this
固定为 undefined
,不再默认指向全局对象。
如果想让内部函数的 this
指向外部对象(比如 obj
),有三种常用解决方案:
-
用箭头函数 :自动捕获外部作用域的
this
jsconst innerFunc = () => { console.log(this); // 指向 obj };
-
保存外部
this
到变量 (经典self
技巧)jsconst self = this; // 保存 obj 到 self function innerFunc() { console.log(self); // 指向 obj }
-
用
bind
绑定this
jsconst boundFunc = innerFunc.bind(this); boundFunc(); // 指向 obj
3. 禁止删除变量/函数:避免误操作
普通模式下,删除变量、函数或函数参数不会报错(但实际也删不掉);严格模式下,这类操作会直接抛出语法错误,避免「误删关键资源」。
js
// 普通模式:删除变量不报错,但无效
var b = 20;
delete b; // 返回 false(删除失败)
console.log(b); // 仍输出 20
// 严格模式:删除变量直接报错
"use strict";
var b = 20;
delete b; // SyntaxError: Delete of an unqualified identifier in strict mode
同样,删除函数、函数参数也会报错:
js
"use strict";
function sayHello() {}
delete sayHello; // 报错
function func(x) {
delete x; // 报错
}
4. 禁止函数参数重名:杜绝参数覆盖
普通模式下,允许函数参数重名,后面的参数会覆盖前面的参数(比如 function func(x, x) {}
);严格模式下,参数重名直接报错,避免「参数值被意外覆盖」的隐蔽 bug。
js
// 普通模式:参数重名不报错,后值覆盖前值
function duplicateParams(x, x) {
console.log(x); // 输出 2(第二个 x 覆盖第一个)
}
duplicateParams(1, 2);
// 严格模式:参数重名直接报错
"use strict";
function duplicateParams(x, x) {}
// SyntaxError: Duplicate parameter name not allowed in this context
5. 禁止八进制字面量:统一数字语法
普通模式下,以 0
开头的数字会被解析为八进制(比如 0123
等于十进制 83
);但这种语法不直观,且容易和十进制数字混淆。严格模式禁止这种写法,推荐用 0o
前缀表示八进制(更规范)。
js
// 普通模式:0123 被解析为八进制
var octalOld = 0123;
console.log(octalOld); // 输出 83
// 严格模式:0123 报错,0o123 合法
"use strict";
var octalOld = 0123; // SyntaxError: Octal literals are not allowed in strict mode
var octalNew = 0o123; // 合法,输出 83
6. 其他重要限制:细节处规避风险
除了上述核心限制,严格模式还有几个实用规则:
-
禁止
with
语句 :with
会动态改变作用域链,导致代码难以理解和优化,严格模式直接禁用;js"use strict"; const obj = { prop: 1 }; with (obj) { prop = 2; } // SyntaxError: Strict mode code may not include a with statement
-
禁止在代码块中声明函数 :
if
、for
等代码块中声明函数会报错(避免作用域混乱); -
eval()
更安全 :eval
内创建的变量不会污染外部作用域(比如eval("var a = 10")
后,外部无法访问a
); -
禁止修改只读属性 :尝试修改对象的只读属性(比如
Object.freeze(obj)
后的对象)会报错,而非静默失败。
三、为什么必须用严格模式?
很多开发者觉得「严格模式限制太多,没必要用」,但实际上,它的好处远大于「不便」:
- 提前暴露 bug:未声明变量、参数重名等问题,在普通模式下可能隐藏很久,严格模式会直接报错,帮你在开发阶段解决问题;
- 减少全局污染 :禁止未声明变量自动成为全局变量,避免意外覆盖
window
上的原生属性(比如window.alert
); - 提升代码性能 :严格模式下,JS 引擎无需处理「自动绑定全局
this
」「动态作用域链(with
)」等复杂逻辑,可以更好地优化代码; - 适配现代 JS:ES6+ 特性(如箭头函数、模块)的设计都基于严格模式,不用严格模式会导致部分新特性无法正常工作;
- 工具默认支持:webpack、Vite 等构建工具会自动在打包后的代码中添加严格模式,与其被动接受,不如主动适配。
四、实际开发中的最佳实践
掌握严格模式的「用法技巧」,才能真正发挥它的价值:
1. 启用方式:全局 vs 局部
- 全局启用 :在脚本文件最顶部添加
"use strict"
(适合独立 JS 文件); - 局部启用:在函数内部顶部添加(适合老项目迁移,避免全局影响其他非严格模式代码);
- ES 模块无需手动加 :使用
import
/export
的文件默认启用严格模式。
2. webpack 中如何控制严格模式?
webpack 会默认在打包后的代码中添加严格模式,如果确实需要禁用(不推荐),可以通过 TerserPlugin
配置:
js
// webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
strict: false, // 禁用严格模式
},
},
}),
],
},
};
3. 开发工具辅助:提前发现问题
在 VS Code 等 IDE 中,开启「严格模式检查」:
- 安装 ESLint 插件,配置
eslint:recommended
规则(默认包含严格模式检查); - 编写代码时,未声明变量、参数重名等问题会实时标红,无需等到运行时才发现。
五、记忆口诀:30 秒记住核心规则
为了方便记忆,我们总结一句口诀,涵盖严格模式的核心限制:
javascript
未声明变量不能用,删除变量行不通;
this 指向要明确,参数不能重复用;
八进制数弃旧法,with 语句全禁用;
eval 不污染作用域,只读属性别改动。
六、总结:严格模式是代码的「安全气囊」
如果把 JS 代码比作一辆车,普通模式就像没有安全气囊的旧车------看似灵活,实则风险重重;而严格模式则是现代汽车的「安全气囊+安全带」,用规则守护代码安全,用规范提升开发效率。
在现代前端开发中,严格模式早已不是「可选配置」,而是「标配要求」。无论是自己写代码,还是维护老项目,都建议主动启用严格模式------它或许会让你在写代码时多花一点时间规范语法,但能帮你避免无数个线上隐蔽 bug。
从今天开始,给你的 JS 代码戴上「严格模式」这副安全眼镜吧!