JS专题之严格模式
ECMAScript 5 引入了 strict mode ,现在已经被大多浏览器实现(从 IE10 开始)
一、什么是严格模式
顾名思义,JavaScript 严格模式就是让 JS 代码以更严格的模式执行,不允许可能会引发错误的代码执行。在正常模式下静默失败的代码,严格模式下就会抛出错误。
二、为什么要过渡到严格模式
- 严格模式下的代码在运行的时候,更容易通过抛出的错误定位到问题所在的地方
- 严格模式能够帮助你编写更符合规范的代码
- 消除 JavaScript 语言上一些不合理,比较怪异的行为
- 为未来新版本的 JavaScript 做铺垫
- 有时候,严格模式下的 JavaScript 代码运行起来更快
三、如何使用
· 脚本文件范围
将
"use strict";
放在脚本文件的第一行。整个脚本文件就会以“严格模式”执行。
· 函数作用域范围
将
"use strict";
放在函数体的第一行,则整个函数以”严格模式”运行。
文件合并时,写在脚本文件第一行的 "use strict";
来实现严格模式会失效,可以将脚本文件的代码放在一个立即执行表达式中。
1 | (funciton() { |
四、严格模式的具体定义
- 严格模式下无法再隐式创建全局变量
也就是,变量必须声明后才能使用,正常模式直接赋值给一个未定义的变量时,会将变量定义为全局变量。
1 | ; |
- 禁止
this
关键字指向全局对象
正常模式下,函数中如果没有指明this
对象,JS 则会将this
隐式指向为全局对象。如果绑定的值是非对象,将被自动转为对象再绑定上去,而 null 和undefined
这两个无法转成对象的值,将被忽略。
严格模式下,必须指明 this
的指向对象。如果没有指明的话,this
的值为 undefined
1 | var name = "foo"; |
- 不允许在函数内部遍历调用栈
禁止使用arguments.callee、arguments.caller、fn.caller、fn.callee
;
在严格模式下,arguments.callee 是一个不可删除属性,而且赋值和读取时都会抛出异常
1 | function func() { |
- 禁止向对象的只读属性赋值,禁止删除对象的不可设置属性, 禁止向不可扩展的对象添加属性
无法删除 var 声明的变量。
在正常模式中,给对象的只读属性赋值, 删除对象的不可设置属性,添加不可扩展对象的新属性,会静默失败。
但是在严格模式中,会抛出错误。
另外,字符串的属性 length 也是只读属性,修改后会报错。
1 | ; |
- 对象不允许有重名的属性,函数不允许有重名的参数
在正常模式中,对象的重名属性,位置靠后会覆盖位置靠前的重名属性。函数也是,函数体查找到的参数,靠后的重名参数会覆盖靠前的重名参数。
1 | ; |
- 静态绑定
JavaScript 支持动态绑定,也就是 JavaScript 的属性和方法是在运行时确定,而不是在编译时确定。
于是,JavaScript 严格模式禁用了 with 语句, 因为使用了 with 语句,with 语句块中变量无法确定是外部全局变量还是传入的对象属性。
1 | ; |
eval 关键字不再会给上层函数(surrounding function)或者全局引入一个新的变量。在严格模式中,eval 语句会创建自己的一个作用域,eval 里的变量只能在 eval 内部使用。
- arguments 的限定
严格模式规定名称为 eval 和 arguments 不能通过程序语法被绑定(be bound)或赋值
严格模式下,参数的值不会随 arguments 对象的值的改变而变化。
正常模式中,对参数重新赋值,会修改 arguments 类数组对象下的参数值。同时,修改 arguments 类数组对象的值,也会修改函数参数的值。
严格模式下,不仅参数的值不会随着 arguments 类数组对象的变化而变化,参数的变化也不会引起 arguments 对象的变化,arguments 对象会记住参数的传入初始值。
1 | function func(a) { |
- ES5 禁止在非函数代码块声明函数
ES5 的严格模式只允许在全局作用域或函数作用域声明函数。也就是说,不允许在非函数的代码块内声明函数。
1 | if (true) { |
- 保留关键字
严格模式中一部分字符变成了保留的关键字。这些字符包括implements, interface, let, package, private, protected, public, static
和yield
。在严格模式下,你不能再用这些名字作为变量名或者形参名
1 | function private() {"use strict" } //Uncaught SyntaxError: Unexpected strict mode reserved word |
- 严格模式禁止八进制数字语法
五、向严格模式过渡
严格模式能够帮助我们写出更安全,更有规范的代码,则应该避免一些危险的写法,采用更好的写法:
- 变量先声明,再使用,
- this 应该在指向自己创建的对象时使用。
- arguments 应该在函数第一行就拷贝出来。
六、严格模式的缺点
- 现在的代码都会进行文件压缩和合并,此时严格模式就会失效。
总结
现在的 webpack 会在打包的时候默认是严格模式,所以现在不用再手动写 use strict
了。严格模式能帮助我们以更规范的方式书写代码,但是无论是否严格模式,都应该注意代码的规范,避免隐式 bug 的出现。
2018/02/08 @Starbucks