严格模式
当启用了严格模式(strict mode)后,JavaScript 就会在执行代码时变得更为严格。我们只需在文件或函数体顶部放置字符串"use strict"
就可以启用严格模式了。下面是示例代码:
function canYouSpotTheProblem() {
"use strict";
for (counter = 0; counter < 10; counter++) {
console.log("Happy happy");
}
}
canYouSpotTheProblem();
// → ReferenceError: counter is not defined
通常,当你忘记在绑定前面放置let
时,就像在示例中的counter
一样,JavaScript 静静地创建一个全局绑定并使用它。 在严格模式下,它会报告错误。 这非常有帮助。 但是,应该指出的是,当绑定已经作为全局绑定存在时,这是行不通的。 在这种情况下,循环仍然会悄悄地覆盖绑定的值。
严格模式中的另一个变化是,在未被作为方法而调用的函数中,this
绑定持有值undefined
。 当在严格模式之外进行这样的调用时,this
引用全局作用域对象,该对象的属性是全局绑定。 因此,如果你在严格模式下不小心错误地调用方法或构造器,JavaScript 会在尝试从this
读取某些内容时产生错误,而不是愉快地写入全局作用域。
例如,考虑下面的代码,该代码不带new
关键字调用构造器,以便其this
不会引用新构造的对象:
function Person(name) { this.name = name; }
let ferdinand = Person("Ferdinand"); // oops
console.log(name);
// → Ferdinand
虽然我们错误调用了Person
,代码也可以执行成功,但会返回一个未定义值,并创建名为name
的全局绑定。而在严格模式中,结果就不同了。
"use strict";
function Person(name) { this.name = name; }
let ferdinand = Person("Ferdinand");
// → TypeError: Cannot set property 'name' of undefined
JavaScript 会立即告知我们代码中包含错误。这种特性十分有用。
幸运的是,使用class
符号创建的构造器,如果在不使用new
来调用,则始终会报错,即使在非严格模式下也不会产生问题。
严格模式做了更多的事情。 它不允许使用同一名称给函数赋多个参数,并且完全删除某些有问题的语言特性(例如with
语句,这是错误的,本书不会进一步讨论)。
简而言之,在程序顶部放置"use strict"
很少会有问题,并且可能会帮助你发现问题。