一、什么是严格模式
严格模式是 ECMAScript 5 引入的一种代码运行模式,它通过限制一些不规范的语法行为、禁止某些潜在的错误操作、抛出更多明确的异常,来让代码运行更安全、更规范,同时也为后续的 ES 版本特性提供了更好的兼容性。
简单来说,严格模式就是给 JavaScript 代码加上了一套「语法约束规则」,让开发者更早发现代码中的问题,减少隐蔽的 bug。
二、如何启用严格模式
严格模式的启用分为「全局启用」和「局部启用」(推荐局部启用),语法非常简单,使用字符串指令 "use strict";(单双引号均可,也可写成 'use strict';)。
1. 全局启用(不推荐,存在隐患)
将 "use strict"; 放在脚本文件的最顶部(在任何其他代码之前),则整个脚本文件内的代码都将运行在严格模式下。
javascript
运行
javascript
// 全局启用严格模式(脚本最顶部,无任何代码前置)
"use strict";
let a = 10;
a = 20; // 正常执行
隐患:如果该脚本文件被其他非严格模式的脚本引入,可能会影响其他脚本的运行;同时,全局严格模式会污染整个作用域,不利于代码模块化。
2. 局部启用(推荐,模块化隔离)
将 "use strict"; 放在函数体的最顶部,则仅该函数内部的代码运行在严格模式下,外部代码不受影响。这是最安全的方式,尤其适合在函数、对象方法、模块化代码中使用。
javascript
运行
scss
// 普通模式(外部代码)
function normalFunc() {
b = 30; // 普通模式下:未声明的变量会隐式挂载到 window 上,不报错
}
// 局部启用严格模式(函数内部最顶部)
function strictFunc() {
"use strict";
let c = 40;
d = 50; // 严格模式下:会抛出异常,禁止隐式声明全局变量
}
normalFunc(); // 正常执行
strictFunc(); // 报错:ReferenceError: d is not defined
三、严格模式的核心特性(与普通模式的关键区别)
严格模式的核心变化是「禁止不良行为」和「抛出更多异常」,以下是最常用、最关键的几个特性:
1. 禁止隐式声明全局变量(核心变化之一)
普通模式下,未使用 var/let/const 声明的变量,会被隐式挂载到全局对象(浏览器中是 window)上,不会报错,这是很多全局变量污染和 bug 的根源。
严格模式下,未声明直接赋值的变量会抛出 ReferenceError 异常,强制开发者必须显式声明变量。
javascript
运行
javascript
"use strict";
// 错误:未声明变量直接赋值,抛出 ReferenceError
x = 100;
// 正确:显式使用 let/const/var 声明变量
let y = 200;
2. 禁止对只读属性 / 不可写属性 赋值,禁止删除不可配置属性
普通模式下,对只读属性赋值、删除不可配置属性只会「静默失败」(不报错,但操作无效),很难被发现;严格模式下,这些操作会直接抛出 TypeError 异常,明确告知开发者操作无效。
javascript
运行
javascript
"use strict";
// 1. 对只读属性赋值(报错)
const obj = Object.defineProperty({}, "name", {
value: "张三",
writable: false // 只读属性,不可修改
});
obj.name = "李四"; // 严格模式下:抛出 TypeError: Cannot assign to read only property 'name'
// 2. 删除不可配置属性(报错)
Object.defineProperty(obj, "age", {
value: 20,
configurable: false // 不可配置,无法删除
});
delete obj.age; // 严格模式下:抛出 TypeError: Cannot delete property 'age'
3. 禁止删除变量 / 函数 / 函数参数
普通模式下,删除变量(delete a)只会返回 false,静默失败;严格模式下,删除变量、函数、函数参数会抛出 SyntaxError 或 ReferenceError 异常 ,只有对象的可配置属性才能被 delete。
javascript
运行
javascript
"use strict";
let num = 10;
function fn() {}
// 错误:删除变量,抛出 SyntaxError
delete num;
// 错误:删除函数,抛出 SyntaxError
delete fn;
// 正确:删除对象的可配置属性
let person = { name: "张三" };
delete person.name; // 执行成功,返回 true
4. 禁止函数参数重名
普通模式下,函数参数可以重名(如 function fn(a, a) {}),后面的参数会覆盖前面的;严格模式下,函数参数不能重名 ,否则会抛出 SyntaxError 异常。
javascript
运行
javascript
"use strict";
// 错误:参数重名,抛出 SyntaxError
function fn(a, a) {
return a + a;
}
// 正确:参数唯一
function fn2(a, b) {
return a + b;
}
5. this 指向的变化(重要区别)
严格模式下,this 的指向与普通模式有明显不同,主要体现在两个场景:
- 全局作用域中,普通函数的
this指向全局对象(浏览器中是window);严格模式下,全局作用域中普通函数的this为undefined(不再指向window)。 - 构造函数忘记使用
new调用时,普通模式下this指向window,会隐式创建全局变量;严格模式下,未使用new调用构造函数,this为undefined,会抛出TypeError异常。
javascript
运行
javascript
"use strict";
// 场景 1:全局函数的 this 为 undefined
function globalFunc() {
console.log(this); // 输出:undefined
}
globalFunc();
// 场景 2:构造函数忘记 new 调用(报错)
function Person(name) {
this.name = name; // 严格模式下:抛出 TypeError: Cannot set property 'name' of undefined
}
let p = Person("张三"); // 未使用 new,直接调用
6. 禁止使用一些保留字 和不规范语法
严格模式下,禁止使用 ES 保留字作为变量名 / 函数名(如 let, const, class, export, import 等),同时禁止一些不规范的语法(如 with 语句、arguments.callee、arguments.caller 等),使用这些语法会抛出异常。
javascript
运行
javascript
"use strict";
// 错误:使用 with 语句,抛出 SyntaxError(严格模式禁止 with)
with (Math) {
console.log(sqrt(16));
}
// 错误:使用 arguments.callee,抛出 TypeError(严格模式禁止)
function factorial(n) {
return n <= 1 ? 1 : n * arguments.callee(n - 1);
}
四、严格模式与之前 for...in 中 const 的关联
补充说明你上一个问题中 for...in 循环使用 const 与严格模式的关系:
for...in/for...of循环中使用const声明迭代变量,在严格模式和普通模式下都可以正常运行,不会因为严格模式而报错;- 严格模式不会改变「
for...in每次迭代创建全新变量绑定」的机制,const声明的迭代变量依然符合「不重新赋值」的约束,因此可以正常使用; - 反而,严格模式会禁止
for...in循环中一些不规范的操作(如迭代变量未声明),让代码更严谨。
javascript
运行
javascript
"use strict";
// 严格模式下,for...in 用 const 声明迭代变量,正常执行
for (const propName in window) {
console.log(propName);
}
总结
- 严格模式通过
"use strict";启用,推荐局部(函数内)启用,避免污染全局作用域; - 核心特性是「禁止不良行为、抛出更多异常」,关键包括禁止隐式全局变量、禁止参数重名、
this指向变化等; - 严格模式让代码更安全、更规范,减少隐蔽 bug,是现代 JavaScript 开发的良好实践;
for...in中使用const在严格模式下完全兼容,不受严格模式影响。