ECMAScript 5 首次引入严格模式的概念。严格模式用于选择以更严格的条件检查 JavaScript 代码错误,可以应用到全局,也可以应用到函数内部。严格模式的好处是可以提早发现错误,因此可以捕获某些 ECMAScript 问题导致的编程错误。
理解严格模式的规则非常重要,因为未来的 ECMAScript 会逐步强制全局使用严格模式。严格模式已得到所有主流浏览器支持。


1. 选择使用

要选择使用严格模式,需要使用严格模式编译指示(pragma),即一个不赋值给任何变量的字符串:

  1. "use strict";

这样一个即使在 ECMAScript 3 中也有效的字符串,可以兼容不支持严格模式的 JavaScript 引擎。支持 严格模式的引擎会启用严格模式,而不支持的引擎则会将这个编译指示当成一个未赋值的字符串字面量。 如果把这个编译指示应用到全局作用域,即函数外部,则整个脚本都会按照严格模式来解析。这意 味着在最终会与其他脚本拼接为一个文件的脚本中添加了编译指示,会将该文件中的所有 JavaScript 置于严格模式之下。
也可以像下面这样只在一个函数内部开启严格模式:

  1. function doSomething() {
  2. "use strict";
  3. // 其他代码
  4. }

如果你不能控制页面中的所有脚本,那么建议只在经过测试的特定函数中启用严格模式


2. 变量

严格模式下如何创建变量及何时会创建变量都会发生变化。第一个变化是不允许意外创建全局变量。在非严格模式下,以下代码可以创建全局变量:

  1. // 变量未声明
  2. // 非严格模式:创建全局变量
  3. // 严格模式:抛出 ReferenceError
  4. name = "another";

在普通模式下这样不带let关键字声明会让变量上升为全局变量,但在严格模式下,这样的行为会报错

相关的另一个变化是无法在变量上调用 delete。在非严格模式下允许这样,但可能会静默失败(返回false).
在严格模式下尝试删除变量会出错

  1. // 删除变量
  2. // 非严格模式:静默失败
  3. // 严格模式:抛出 ReferenceError
  4. let color = "red";
  5. delete color;

严格模式也对变量名增加了限制。具体来说,不允许变量名为 implements、interface、let、package、private、protected、public、static 和 yield。这些是目前的保留字,可能在将来的 ECMAScript 版本中用到。如果在严格模式下使用这些名称作为变量名,则会导致语法错误。


3. 对象

在严格模式下操作对象比在非严格模式下更容易抛出错误。严格模式倾向于在非严格模式下会静默 失败的情况下抛出错误,增加了开发中提前发现错误的可能性。
首先,以下几种情况下试图操纵对象属性会引发错误。

  • 给只读属性赋值会抛出 TypeError。
  • 在不可配置属性上使用 delete 会抛出 TypeError。
  • 给不存在的对象添加属性会抛出 TypeError。

另外,与对象相关的限制也涉及通过对象字面量声明它们。在使用对象字面量时,属性名必须唯一。

  1. // 两个属性重名
  2. // 非严格模式:没有错误,第二个属性生效
  3. // 严格模式:抛出 SyntaxError
  4. let person = {
  5. name: "yuanmou",
  6. name: "weiyuequn"
  7. };

这里的对象字面量 person 有两个叫作 name 的属性。第二个属性在非严格模式下是最终的属性。 但在严格模式下,这样写是语法错误。

注意 ECMAScript 6 删除了对重名属性的这个限制,即在严格模式下重复的对象字面量属性键不会抛出错误。