Skip to content

严格模式

严格模式是 ES5 引入的特性,它对 JavaScript 语法和行为施加更严格的限制,帮助开发者编写更安全、更高效的代码。

🎯 启用严格模式#

全局严格模式#

// 在脚本开头添加
'use strict'
// 之后的所有代码都在严格模式下运行
x = 10 // ReferenceError: x is not defined

函数级严格模式#

// 只在函数内启用
function strictFunc() {
'use strict'
// 这里是严格模式
x = 10 // ReferenceError
}
function normalFunc() {
// 这里是普通模式
y = 20 // 创建全局变量(不推荐)
}

模块自动启用#

module.js
// ES6 模块默认启用严格模式
export function example() {
// 自动处于严格模式
undeclared = 1 // ReferenceError
}
// 类内部也是严格模式
class MyClass {
method() {
// 严格模式
undeclared = 1 // ReferenceError
}
}

变量相关限制#

必须声明变量#

'use strict'
// 🔶 普通模式:创建全局变量
// x = 10 // window.x = 10
// ✅ 严格模式:必须先声明
let x = 10
const y = 20
var 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 // TypeError

getter-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 } = obj
console.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 = 10
eval('let x = 20; console.log(x)') // 20
console.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 和参数不同步,避免额外开销

实际应用#

模块化代码#

utils.js
// 现代 JavaScript 开发推荐使用模块
// 模块自动启用严格模式
export function formatDate(date) {
// 自动严格模式
// ...
}
// main.js
import { 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 = 8SyntaxError
with 语句允许SyntaxError
this(普通函数调用)windowundefined
只读属性赋值静默失败TypeError
场景严格模式状态
<script> 顶部 'use strict'开启
函数内部 'use strict'该函数开启
ES6 模���自动开启
ES6 类自动开启
箭头函数继承外层

核心要点