最近看一些源码的时候经常看到’use strict’ 严格模式,对这个概念有点模棱两可。感觉 ES 5的严格模式和ES6有些地方有点相似,比如变量提升。这个可能注定要被历史掩埋,翻出来整理下纯粹为了好玩。
“use strict” 是 ECMAScript 5引入的一条指令。指令不是语句(但非常接近于语句)
先科普下指令和语句之间的两个重大的区别
它不包含其他语言的关键字。
指令仅仅是一个包含一个特殊字符串直接量的表达式。对于没有支持ECMAScript 5解释器的浏览器,“use strict” 只是个没有副作用的表达式语句。将来如果 user被作为关键字的时候,将不需要引号
ps:大部分浏览器都支持ECMAScript 5的 javascript解释器, 但是 ie8对ECMAScript大部分功能支持,但不支持strict mode
它只能出现脚本代码的开始或者函数体的开始、任何实体语句之前。
这里其实有点疑义,’use strict’可以不在第一行,只要前面不是产生实际运行结果的语句,比如直接跟在一个空的分好后面。
|
|
上面代码中,前一个script标签是严格模式,后一个标签不是严格模式
严格模式和非严格模式的区别
严格模式下,this指向的值是undefined, 非严格模式下this 指向的是全局变量
|
|
可以利用这种特性来判断javascript实现是否支持严格模式
严格模式禁止使用 with语句
with语句用于扩展临时作用域链
|
|
但是必须一提的是,with 有两个致命缺点。一个是难于优化,一个是运行比较慢,所以在严格模式中是被禁止使用的。
严格模式中,所有变量都要先申明
如果给一个为申明的变量、函数、函数参数、catch从句参数或全局对象的属性赋值,将会抛出一个错误异常。这个跟ES 6中的没有变量提升一样,变量得先定义在使用。
在非严格模式中,这种隐式申明的全局变量的方法是给全局对象新添加一个新属性
call() 或 apply()
在严格模式中,通过 call() 或 apply() 来调用函数时,其中的this值就是传入的第一个参数
在非严格模式中,null 和 undefined 值被全局对象和转换为对象的的非对象值所替代
只读和不可扩展对象
严格模式下,给只读和不可扩展对象创建新成员都将抛出一个类型错误
非严格模式,这些操作只是简单的操作失败,不会报错
eval()
在严格模式中,传入eval()的代码不能再调用程序所在的上下文中声明变量或定义函数。变量和函数的定义是在eval()创建新的作用域,在eval()返回时,作用域就被弃用了。
正常模式下,eval()的作用域取决于所处全局作用域,或者处于函数的局部作用域。
|
|
arguments 对象
在严格模式,传入参数arguments拥有传入传入函数值的静态副本。
所以你不允许对arguments进行操作。
|
|
在非严格模式,arguments的数组元素和函数参数都是指向同一个值的引用。
|
|
delete
严格模式下,就变得严格的,当 delete运算符后跟随非法的标识符。将抛出一个语法错误。
|
|
同名错误
在严格模式中,在一个对象直接量中定义两个或多个同名属性将会报错。
但在浏览器是了下同名并不会报错
|
|
重名的参数
八进制
严格模式是不允许使用八进制整数直接量,以0为前缀,而不是已0x为前缀。
caller
匿名函数无法在内部调用自身
|
|
目的
- 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
- 消除代码运行的一些不安全之处,保证代码运行的安全;
- 提高编译器效率,增加运行速度;
- 为未来新版本的Javascript做好铺垫。
缺点
现在网站的 JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。
更多内容可以参考阮老师的文章 Javascript 严格模式详解