一篇文章图文并茂地带你了解 JavaScript 严格模式(strict mode)
JavaScript 严格模式 use strict
前言
在很长的一段时间内,JavaScript
是兼容性发展的。这意味着新的语言特性并不会影响原有的代码。但是也带来了一些缺点,一些 JavaScript
的设计者做出的不太好的决定或失误被永远的加入了JavaScript
。
这种情况直到 ES5
的出现得到了改变。我们可以在代码的首部添加特殊的指令 use strict
来使某些不良的 JavaScript
特性得到改善。
本文对于读者来说是补充知识的文章,由于现在许多前端学习者包括笔者是从 ES6
语法后才开始学的 JavaScript
。因此其实已经站在巨人的肩膀上,尽管没有特殊表明使用严格模式,却没有使用 JavaScript
内的 "糟粕"。
因此本文较适合想补充更多知识,了解 JavaScript
历史的读者,或是跟着比较老旧教程学习,曾经在几年前学习过 JavaScript
的读者。
严格模式 use strict
use strict
指令可以在代码的头部使用,如果放在代码的头部,则认为整个文件都将采用严格模式。
"use strict"; // or 'use strict';
a = 1; // a is not defined
如果放在函数开始,则认为只有某个函数用了严格模式,如
(function() {
"use strict";
// ...
})
需要注意,严格模式一旦开启,就不能 "反悔",即没有指令可以暂停严格模式。
什么时候需要严格模式?
除非有老旧代码,大多数情况下我们都推荐使用严格模式。
不过如果在模块或者类等现代 JavaScript
语言特性中,可以省略 use strict
,因为已经默认开启了严格模式。
class Person {
constructor() {
age = 22;
}
}
new Person(); // age is not defined
注: 只是对这些语法使用的地方生效,并非使用了类,就对整个文件生效严格模式。
class Person {}
a = 1; // ok
严格模式对编码的影响
1. 全局变量显式声明
age = 22; // window.age = 22
本来为了方便初学者,有意让变量在使用前无须声明。但是这些忘记声明的变量都成为了全局变量。在严格模式下,必须显式声明。
"use strict"
age = 22; // age is not defined
2. 禁止使用 with 语句
JavaScript
语言允许 动态绑定,意味着某些属性和方法到底属于哪个对象,不是编译的时候确定,而是运行的时候确定的。这会减慢 JavaScript
处理器的处理速度。
严格模式对动态绑定做了限制。
JavaScript
提供了 with
语句,本意是快捷访问对象的属性。不幸的是,结果可能不可预料。
with(obj) {
a = b;
}
可能和下面某个语句是一致的
a = b;
obj.a = b;
a = obj.b;
obj.a = obj.b;
通过阅读代码,无法确定会执行某一条语句。
- 禁止
this
关键字指向全局对象
如果没有明确指明是谁调用的函数,在浏览器下,默认是 window
function Person() {
this.name = "huro";
}
const p = Person();
这使得我们给 window.name
赋值了 huro
实际上或许我们是漏了 new
关键字。
但没有任何方式可以区分一个函数是构造函数还是普通函数。
在严格模式下直接调用函数 this
不再指向全局对象,而是 undefined
"use strict";
function Person()
this.name = "huro";
}
const p = Person(); // can't set property of undefined
- 更多的作用域
正常模式下,JavaScript语言有两种变量作用域
- 全局作用域
- 函数作用域
function fn(){
// 函数作用域
}
在严格模式下,有额外的两种变量作用域
- 块级作用域
需要注意的是,由于 ES6
新增了 const
以及 let
语法,因此使用这两种语法定义的变量默认就有块级作用域。
"use strict";
if (true) {
// 块级作用域
}
eval
作用域
"use strict";
eval("console.log('huro')")
对于更多的 strict mode
下的影响。
可以参阅 阮一峰 strict mode 不过笔者认为里面的内容已经有些老旧了。
也可以参阅 MDN Strict mode
总结
严格模式可以说是摒弃了非常多 JavaScript
的语言糟粕,同时也为 ES5
以后的新增的语法特性做铺垫。