本文深入解析 JavaScript 严格模式(Strict Mode)与非严格模式的核心区别。详细讲解如何通过 "use strict" 开启全局或函数级严格模式,并对比两者在禁止意外全局变量、限制只读属性修改、this 指向变化及重复参数名处理等方面的具体差异。文章强调现代开发中严格模式的必要性,并提供最佳实践建议。
这是一个基础且关键的 JavaScript 概念,我们将深入解析严格模式(Strict Mode)与非严格模式(Sloppy Mode)的具体差异。
为了便于理解,我们可以将其类比为两种不同的考试场景:
- 非严格模式类似于开卷且不限时的随堂测验,规则相对宽松,即使代码书写不够规范也能通过,解释器会尝试推测开发者的意图。
- 严格模式则如同正式的闭卷考试,有着严格的规范约束,任何不符合语法规则的写法都会立即被标记为错误,没有任何妥协空间。
1. 什么是严格模式?
严格模式是 ECMAScript 5 (ES5) 引入的一种可选机制,它为 JavaScript 代码应用了更严格、受限的语法和错误处理规则。
其核心目的是让 JavaScript 引擎以更为严谨的方式解析和执行代码,从而显著提升代码的健壮性与安全性。
相比之下,非严格模式(Sloppy Mode)是 JavaScript 默认的、为了向后兼容而设计的更为宽容的运行模式。
2. 为什么需要严格模式?
JavaScript 最初设计为一种高度宽容的语言,旨在确保网页在各种意外情况下仍能运行而非直接崩溃。然而,这种宽容性也引发了一系列问题:
- 静默错误 (Silent Errors):某些本应报错的操作在非严格模式下不会抛出异常,而是静默失败,这极大增加了调试难度。
- 不安全的行为:部分语法可能存在安全隐患,或者导致意外污染全局变量。
- 阻碍引擎优化:一些“不良语法”结构使得 JavaScript 引擎难以对代码进行高效的性能优化。
- 为未来做准备:严格模式禁止使用一些未来可能被保留作为关键字的标识符。
严格模式的引入正是为了解决上述历史遗留问题。
3. 如何开启严格模式?
开启严格模式非常简便,只需在代码的特定位置添加一个字符串字面量:
"use strict";
根据该字符串放置的位置不同,其作用域也会有所区别:
全局严格模式:将 "use strict"; 放置在脚本文件的最顶部。
// my-script.js
"use strict";
// 整个文件都将以严格模式运行
let x = 10;
// ...
函数内严格模式:将 "use strict"; 放置在函数体的最顶部。
function myStrictFunction() {
"use strict";
// 只有这个函数内部是以严格模式运行的
let y = 20;
// ...
}
一个重要的现代开发知识点:
在 ES6 模块(使用 import/export)以及 class 代码块中,严格模式是默认开启的,无需手动添加 "use strict"。这也是为什么在现代前端框架(如 React、Vue)的开发中,你很少看到这行代码,因为现代前端代码基本都运行在严格模式的模块环境中。
4. 严格模式与非严格模式的主要区别
以下是几个最直观且重要的区别,通过代码对比可以清晰展示:
a. 禁止意外创建全局变量
这是最经典的区别之一。
非严格模式下:
function createGlobal() {
mistake = "I am a global variable!"; // 忘记写 let/const/var
}
createGlobal();
console.log(window.mistake); // "I am a global variable!" (在浏览器中)
// 变量泄漏到了全局作用域,这是一个非常危险的副作用。
严格模式下:
"use strict";
function createGlobal() {
mistake = "This will cause an error";
}
// createGlobal(); // 这一行会直接抛出 ReferenceError,程序会中断
结论:严格模式将一个常见的“静默错误”转化为“抛出错误”,使开发者能够立即发现并修复问题。
b. 禁止对只读属性或不可扩展对象进行修改
非严格模式下:
const obj = {};
Object.defineProperty(obj, 'readOnly', { value: 10, writable: false });
obj.readOnly = 20; // 尝试修改只读属性
console.log(obj.readOnly); // 10 (修改静默失败,不会报错)
严格模式下:
"use strict";
const obj = {};
Object.defineProperty(obj, 'readOnly', { value: 10, writable: false });
// obj.readOnly = 20; // 这一行会抛出 TypeError
结论:严格模式同样将静默失败的操作转化为明确的错误抛出。
c. this 的指向不同
我们在之前的练习中已经接触过这一概念。
非严格模式下:
function showThis() {
console.log(this);
}
showThis(); // 在浏览器中,会输出全局的 window 对象
严格模式下:
"use strict";
function showThis() {
console.log(this);
}
showThis(); // 输出 undefined
结论:严格模式下的 this 行为更加安全,有效避免了意外污染全局对象的风险。
d. 禁止重复的参数名
非严格模式下:
function sum(a, a, b) { // 不会报错
return a + a + b; // 实际上是第二个 a 生效
}
console.log(sum(1, 2, 3)); // 2 + 2 + 3 = 7
严格模式下:
"use strict";
// function sum(a, a, b) { // 这一行在代码解析阶段就会抛出 SyntaxError
// return a + b;
// }
结论:严格模式在语法解析阶段就杜绝了这种不合理的代码写法。
总结与建议
| 特性 | 非严格模式 (Sloppy Mode) | 严格模式 (Strict Mode) |
|---|---|---|
| 意外全局变量 | 允许,静默创建 | 禁止,抛出 ReferenceError |
| 修改只读属性 | 静默失败 | 禁止,抛出 TypeError |
| 全局函数this | 指向全局对象 (window) | undefined |
| 重复参数名 | 允许(最后一个生效) | 禁止,抛出 SyntaxError |
最终建议:始终使用严格模式!
在当今的 JavaScript 开发中,没有任何理由不使用严格模式。它能帮助你编写出更健壮、更安全、更规范的代码,并避免许多难以调试的“幽灵 bug”。
鉴于现代 JavaScript 的模块和类已经默认开启了严格模式,将 "use strict"; 放在所有非模块化的老脚本的顶部,应成为你的标准编码习惯。
本文关于 js 严格模式和非严格模式区别的介绍到此结束,更多相关 js 严格模式 非严格模式内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!