严格模式是 ES5 引入的特性,它对 JavaScript 语法和行为施加更严格的限制,帮助开发者编写更安全、更高效的代码。
🎯 启用严格模式#
全局严格模式#
// 在脚本开头添加'use strict'
// 之后的所有代码都在严格模式下运行x = 10 // ReferenceError: x is not defined函数级严格模式#
// 只在函数内启用function strictFunc() { 'use strict' // 这里是严格模式 x = 10 // ReferenceError}
function normalFunc() { // 这里是普通模式 y = 20 // 创建全局变量(不推荐)}模块自动启用#
// ES6 模块默认启用严格模式export function example() { // 自动处于严格模式 undeclared = 1 // ReferenceError}
// 类内部也是严格模式class MyClass { method() { // 严格模式 undeclared = 1 // ReferenceError }}变量相关限制#
必须声明变量#
'use strict'
// 🔶 普通模式:创建全局变量// x = 10 // window.x = 10
// ✅ 严格模式:必须先声明let x = 10const y = 20var z = 30禁止删除变量#
'use strict'
let x = 10// delete x // SyntaxError: Delete of an unqualified identifier
// 对象属性可以删除const obj = { a: 1 }delete obj.a // 正常禁止使用保留字#
'use strict'
// 这些不能作为变量名// let implements = 1 // SyntaxError// let interface = 1// let package = 1// let private = 1// let protected = 1// let public = 1// let static = 1// let yield = 1
// 普通模式下部分可以使用(但不推荐)函数相关限制#
函数参数不能重名#
'use strict'
// 🔶 普通模式:允许(后者覆盖前者)// function add(a, a, b) {// return a + b // 使用第二个 a// }
// ✅ 严格模式:报错// function add(a, a, b) { // SyntaxError// return a + b// }
function add(a, b, c) { return a + b + c}禁止使用 arguments.callee#
'use strict'
// 🔶 普通模式:可以递归引用// function factorial(n) {// if (n <= 1) return 1// return n * arguments.callee(n - 1)// }
// ✅ 严格模式:使用命名函数function factorial(n) { if (n <= 1) return 1 return n * factorial(n - 1)}arguments 不与参数绑定#
'use strict'
function example(a) { console.log(a, arguments[0]) // 1, 1
a = 10 console.log(a, arguments[0]) // 10, 1(不再同步)
// 普通模式下 arguments[0] 也会变成 10}
example(1)函数内的 this#
'use strict'
function showThis() { console.log(this)}
showThis() // undefined(普通模式是 window)
// 明确绑定showThis.call({ name: '对象' }) // { name: '对象' }showThis.call(null) // null(普通模式是 window)showThis.call(undefined) // undefined对象相关限制#
只读属性不能赋值#
'use strict'
const obj = {}Object.defineProperty(obj, 'x', { value: 10, writable: false,})
// obj.x = 20 // TypeError: Cannot assign to read only property
// 普通模式下静默失败不可扩展对象不能添加属性#
'use strict'
const obj = { a: 1 }Object.preventExtensions(obj)
// obj.b = 2 // TypeError: Cannot add property b
// Object.seal 和 Object.freeze 同理const frozen = Object.freeze({ x: 1 })// frozen.y = 2 // TypeError// frozen.x = 2 // TypeErrorgetter-only 属性不能赋值#
'use strict'
const obj = { get value() { return 42 },}
// obj.value = 100 // TypeError: Cannot set property value
// 普通模式下静默失败不可配置属性不能删除#
'use strict'
const obj = {}Object.defineProperty(obj, 'x', { value: 10, configurable: false,})
// delete obj.x // TypeError: Cannot delete property 'x'其他限制#
禁止八进制字面量#
'use strict'
// 🔶 普通模式:八进制// const octal = 010 // 8
// ✅ 严格模式:报错// const octal = 010 // SyntaxError
// 使用 0o 前缀const octal = 0o10 // 8(ES6 八进制字面量)禁止 with 语句#
'use strict'
const obj = { a: 1, b: 2 }
// 🔶 普通模式:with 可用(但不推荐)// with (obj) {// console.log(a, b)// }
// ✅ 严格模式:报错// with (obj) { // SyntaxError// console.log(a, b)// }
// 推荐使用解构const { a, b } = objconsole.log(a, b)禁止 eval 创建变量#
'use strict'
// 🔶 普通模式:eval 可以创建变量// eval('var x = 10')// console.log(x) // 10
// ✅ 严格模式:eval 有独立作用域eval('var x = 10')// console.log(x) // ReferenceError: x is not defined
// eval 内部可以访问console.log(eval('var y = 20; y')) // 20严格模式的好处#
捕获编程错误#
'use strict'
// 1. 拼写错误立即报错let userName = 'Zhang'// usernmae = 'Li' // ReferenceError(不是静默创建全局变量)
// 2. 赋值给只读属性报错NaN = 1 // TypeError(普通模式静默失败)
// 3. 给不可扩展对象添加属性报错const fixed = Object.freeze({})// fixed.prop = 1 // TypeError简化变量使用#
'use strict'
// 不再需要担心意外创建全局变量function process() { result = computeValue() // ReferenceError,而不是污染全局}
// 更清晰的作用域function outer() { let x = 1 function inner() { // x = 2 // 必须明确声明,不会意外修改外部变量 let x = 2 // 明确创建新变量 }}更安全的 eval#
'use strict'
// eval 不会影响周围作用域let x = 10eval('let x = 20; console.log(x)') // 20console.log(x) // 10(未被修改)更安全的 this#
'use strict'
// 防止意外修改全局对象function setGlobalValue() { // 普通模式: this 是 window,可能意外修改全局 // 严格模式: this 是 undefined,赋值会报错 this.value = 10 // TypeError: Cannot set property 'value' of undefined}
setGlobalValue()提升性能#
'use strict'
// JavaScript 引擎可以进行更多优化// 1. 变量不会意外变成全局变量// 2. 不需要在运行时检查 with 语句// 3. arguments 和参数不同步,避免额外开销实际应用#
模块化代码#
// 现代 JavaScript 开发推荐使用模块// 模块自动启用严格模式
export function formatDate(date) { // 自动严格模式 // ...}
// main.jsimport { formatDate } from './utils.js'// 也是严格模式类和方法#
// 类内部自动启用严格模式class User { constructor(name) { this.name = name }
greet() { // 严格模式 console.log(`Hello, ${this.name}`) }}立即执行函数#
// 在旧代码中隔离严格模式;(function () { 'use strict'
// 这里是严格模式 // 不影响其他代码})()混��环境#
// 某些代码需要普通模式(如第三方库)// 使用函数隔离严格模式
function strictCode() { 'use strict' // 严格模式代码}
function normalCode() { // 普通模式代码(可能是遗留代码)}常见问题#
第三方库兼容#
// 🔶 问题:某些旧库可能在严格模式下报错
// ✅ 解决:在函数内启用,不影响全局;(function () { 'use strict' // ��的代码})()
// 或使用模块,天然隔离this 绑定变化#
'use strict'
const obj = { name: '对象', greet() { // 方法内 this 正常 console.log(this.name)
// 🔶 普通函数会丢失 this setTimeout(function () { console.log(this) // undefined }, 100)
// ✅ 使用箭头函数 setTimeout(() => { console.log(this.name) // '对象' }, 100) },}构造函数不用 new#
'use strict'
function Person(name) { // 普通模式:this 是 window,会污染全局 // 严格模式:this 是 undefined,会报错 this.name = name // TypeError}
// 🔶 问题// Person('张三') // TypeError
// ✅ 正确使用const person = new Person('张三')
// ✅ 或使用类class PersonClass { constructor(name) { this.name = name }}总结#
| 特性 | 普通模式 | 严格模式 |
|---|---|---|
| 未声明变量赋值 | 创建全局变量 | ReferenceError |
| 删除变量 | 静默失败 | SyntaxError |
| 重复参数名 | 允许 | SyntaxError |
| 八进制字面量 | 010 = 8 | SyntaxError |
| with 语句 | 允许 | SyntaxError |
| this(普通函数调用) | window | undefined |
| 只读属性赋值 | 静默失败 | TypeError |
| 场景 | 严格模式状态 |
|---|---|
<script> 顶部 'use strict' | 开启 |
函数内部 'use strict' | 该函数开启 |
| ES6 模��� | 自动开启 |
| ES6 类 | 自动开启 |
| 箭头函数 | 继承外层 |
核心要点:
- 严格模式让代码更安全、更可预测
- ES6 模块和类自动启用严格模式
- 建议新项目始终使用严格模式
- 注意 this 绑定的变化
- 可以在函数级别启用,不影响其他代码