严格模式
在HTML 5中首次引入了严格模式的概念。严格模式是用更加严格的条件来检查代码的正确性。严格模式可以应用于全局,也可以应用于局部范围。这样可以更好的、更快的发现编译中出现的错误。因此了解严格模式是非常有必要的。现在的主流浏览器都已经接受了严格模式。
既然要用严格模式,就要引用他的编译指示。其实也简单,就是写上一段字符串。
假设现在你要在一个函数内部使用严格模式,你只需要在函数的里面最顶部的位置同样的写上那一段字符串就可以了。
function fn(){
"use strict";
...
}
这段字符串即使在ES 3也是有效的。而且兼容不支持严格模式的JavaScript引擎,在支持的引擎中,就可以按照严格模式的规则进行,在不支持的引擎之中这段字符串只会被当作并未赋值的一段字符。
要在全局应用严格模式并且你是在使用script标签中使用,只需要在标签内的最顶部写上一段字符串就可以了。
<script>
"use strict";
...
</script>
这样就已经启用了严格模式,要注意的是,必须要放在最顶部,不管是全局还是局部的。
应用全局的时候有需要注意的地方:就是应用全局的时候,这意味着在最终会与其他脚本拼接为一个文件的脚本中添加了编译指示,会将该文件中的所有JavaScript置于严格模式之下。
在你能掌控所有的脚本文件的时候,你再在全局中开启严格模式,不然,建议的还是在函数内部使用严格模式。
在严格模式下的对象
可以知道的是,严格模式比非严格模式更容易抛出错误。
首先,以下几种情况下试图操纵对象属性会引发错误。
- 给只读属性赋值会抛出错误。
- 在不可配置属性上使用delete会抛出错误。
- 给不存在的对象添加属性会抛出错误。
这三种情况都会抛出TypeError的错误。另外还有的是,在使用对象的字面量时,属性名是必须是唯一的,不然会抛出错误。
let person = {
name: "Nicholas",
name: "Greg"
// 非严格模式下name最终等于Dreg,
// 严格模式下会抛出错误
};
在非严格模式下,对象属性名相同的情况下,是以最后一个的赋值来生效的。
严格模式刚开始的时候是不允许这种情况发生的,但是在ES 6之后,修改了这种设定,ES 6之后,严格模式允许对象属性名重复使用。
在严格模式下的函数
在非严格模式下,函数的参数名是可以重复的
function fn(num,num){
...
}
在函数参数名重复的情况下,通过参数名只能访问第二个参数,访问不到第一个参数。只能通过arguments的属性来访问第一个参数。虽然这样是有点麻烦,但是却不会抛出错误。
但是在严格模式下,函数的参数名是不可以重复的,并且,在严格模式下的参数和arguments是相互独立的。也就是说,修改参数的值,arguments的值是不会同样的一起被修改。
function fn(num){
num = '你好';
alert(num); // 你好
alert(arguments[0]); // 大家好
}
fn("大家好");
非严格模式下,修改参数值时arguments获取的值是会跟着一起该变的。
另一个变化是去掉了arguments.callee和arguments.caller。在非严格模式下,它们分别引用函数本身和调用函数。严格模式就把这两个都去除了。访问它们时会抛出错误。
function fn(num){
if(num <= 1){
return 1;
}else{
return num * arguments.callee(num-1) // 120
}
}
fn(5)
// 非严格模式下这样不会抛出错误,返回的是120,在严格模式下,
// 会抛出TypeError错误。
同样的,读取或修改 callee 和 caller 的值或者 factorial.callee 和 factorial.caller 一样会抛出错误。
严格模式也限制了函数的命名,不允许函数名为 implements、interface、let、package、private、protected、public、static和yield。
最后一个变化是不允许函数声明。也就是说不可以在if里面声明函数。除非他们位于脚本和函数的顶级。
if(true){
function fn(){
...
}
}
在非严格模式下,函数会提升到if外面,这是可以正常运行的代码,浏览器都支持这种语法。但是在严格模式下,这是不可以的,会抛出错误 SyntaxError,语法错误的意思。