Skip to content

严格模式

严格模式通过 "use strict" 改变一部分 JavaScript 的执行规则,让一些原本会被悄悄忽略的问题,变成更明确的报错。

它的目标不是“让代码更难写”,而是减少历史包袱带来的歧义和隐式行为。

为什么会有严格模式

早期 JavaScript 为了兼容性,保留了不少宽松行为,例如:

  • 给未声明变量赋值时悄悄创建全局变量
  • 某些错误写法静默失败
  • this 在普通函数调用中默认指向全局对象

严格模式的核心价值就是把这些“容易出错但不容易发现”的行为收紧。

如何开启

在脚本顶部开启

js
'use strict'

const name = 'Lee'

当它出现在脚本顶部时,通常表示整个脚本都以严格模式运行。

在函数内部开启

js
function test() {
  'use strict'

  return 1
}

这样只影响当前函数内部。

哪些场景会自动启用

现代 JavaScript 里有两类代码默认就是严格模式:

  • ES Module
  • class

也就是说,在模块文件和类体里,通常不需要再额外写 "use strict"

严格模式最常见的行为变化

不能意外创建全局变量

非严格模式下,下面这种写法可能会偷偷把变量挂到全局对象上:

js
count = 1

严格模式下会直接报错:

js
'use strict'

count = 1 // ReferenceError

这是严格模式最有价值的一点之一,因为它能更早暴露拼写错误和漏写声明的问题。

普通函数里的 this 不再默认指向全局对象

js
'use strict'

function show() {
  console.log(this)
}

show() // undefined

这能避免函数在无意间把数据写到全局对象上。

对只读属性赋值会报错

js
'use strict'

const obj = Object.defineProperty({}, 'name', {
  value: 'Lee',
  writable: false,
})

obj.name = 'Vfan' // TypeError

非严格模式下,这类赋值很多时候只是静默失败。

删除非法目标会报错

js
'use strict'

const value = 1
// delete value // SyntaxError

delete 只适合删除对象属性,不适合删除变量绑定。

with 被禁用

js
'use strict'

// with (Math) {
//   console.log(PI)
// }

with 会让变量解析变得不透明,因此严格模式直接禁止它。

某些历史遗留能力被收紧

例如:

  • 不能给 evalarguments 重新赋值
  • 参数名不能重复
  • arguments.callee 不可用

这些限制的共同方向都是减少动态、模糊和难以优化的行为。

this 的关系尤其值得注意

严格模式最常被感知到的变化之一,就是 this 行为变得更“诚实”。

js
'use strict'

function Person(name) {
  this.name = name
}

// Person('Lee') // TypeError

在这里,如果忘记使用 newthis 不会退回到 window,而是直接暴露问题。

严格模式不等于现代 JavaScript 的全部

严格模式只是一组执行规则的收紧,并不代表:

  • 自动获得模块能力
  • 自动启用 TypeScript 式检查
  • 自动修复所有语言陷阱

它只是让一些危险行为更早失败。

现在还需要手动写 "use strict"

在现代前端项目里,很多文件本身就是模块,因此通常已经默认处于严格模式。

所以实际判断可以是:

  • 如果代码是 ES Module,通常不需要再手写
  • 如果是老脚本、内联脚本或历史代码,仍然可能需要显式写出

使用建议

  • 写现代模块代码时,把“默认严格模式”当作常态理解即可。
  • 阅读老代码时,如果看到一些宽松行为,要先判断当前是否处于严格模式。
  • 当代码在严格模式下报错时,优先把它理解成“更早暴露真实问题”,而不是“模式太严格”。
  • 不要依赖 with、隐式全局变量或 arguments.callee 这类历史能力。

基于 MIT 许可发布