Javascript的严格模式

蚊子前端博客
发布于 2015-02-14 07:00
ES5最早引入了“严格模式”(strict mode)的概念。严格模式不是束缚了开发者的手脚,而是更加规范了Javascript的开发,方便代码的多浏览器兼容和以后的维护

在严格模式下,能够在函数内部选择进行较为严格的全局或局部的错误条件检测。使用严格模式的好处是可以提早知道代码中存在的错误,即使捕获一些可能导致编程uowu的ECMAScript行为。 理解严格模式的规范非常重要,ECMAScript的下一个版本将以严格模式为基础指定。支持严格模式的浏览器包括IE10+,Firefox4+, Safari5.1+和Chrome。

1. 选择使用

要选择进入严格模式,可以使用严格模式的编译指示,实际上就是一个不会赋给任何变量的字符串: use strict; 在老版本的浏览器里,会把它当做一行普通的字符串,加以葫芦。 如果在全局作用域中(函数外部)给出这个编译知识,则整个脚本都将使用严格模式。换句话说,如果把带有这个编译指示的脚本放到其他文件中,则该文件中的Javascript代码将处于严格模式下。 也可以只在函数中打开严格模式,就像下面这样:

COPYJAVASCRIPT

function doSomething(){ "use strict"; // 其他代码 }

如果你没有控制页面中所有脚本的权利,建议只在需要测试的特定函数中开启严格模式。

2. 变量

在严格模式下,什么时候创建变量以及怎么创建变量都是有限制的。首先,不允许意外创建全局变量。在非严格模式下,可以像下面这样创建全局变量。

COPYJAVASCRIPT

// 未声明变量 // 非严格模式:创建全局变量 // 严格模式:抛出错误 message = "hello wenzi";

即使message前面没有var关键字,即使没有将它定义为某个全局对象的属性,也能将message为全局变量。但在严格模式下,如果给一个没有声明的变量赋值,那代码在执行时就会抛出错误。 其实不能对变量调用delete操作符。非严格模式允许这样操作,单户静默失败(返回false),而在严格模式下,删除变量也会导致错误。

COPYJAVASCRIPT

// 删除变量 // 非严格模式:静默失败 // 严格模式:抛出错误 var color = "red"; delete color;

严格模式下对变量名也有限制。特别地,不能使用implements, interface, protected, public, staticyield作为变量名。这些都是保留字,将来的ES版本中可能会使用到他们。在严格模式,用以上的标识符作为变量会导致语法错误。

3. 对象

在严格模式下操作对象比在非严格模式下更容易导致错误。一般来说,非严格模式下会静默失败的情形,在严格模式下就会抛出错误。因此在开发中使用严格模式更能发现错误。 在下列情形下操作对象的属性会导致错误:

  • 为只读属性进行赋值;

  • 为不可配置的属性使用delete操作符;

  • 为不可扩展的对象添加谁能够 使用对象的另一个限制与通过对象字面量声明对象有关。*在使用对象字面量时,属性名必须唯一*。例如:

COPYJAVASCRIPT

// 重名属性 // 非严格模式:没有错误,以第二个属性为准 // 严格模式:抛出语法错误 var student = { name : 'wenzi', name : 'bing' }

这里的对象student有两个属性,都叫name。在非严格模式下,student对象的name属性值是第二个,而在严格模式下,这样的代码会导致语法错误。

4. 函数

首先,严格模式下要求明明函数的参数必须唯一。以下面这个函数为例:

COPYJAVASCRIPT

// 重名参数 // 非严格模式:没有错误,只能访问第二个参数 // 严格模式:抛出语法错误 function doSomething(num, num){ // 其他代码 }

在非严格模式下,这个函数声明不会抛出错误。通过参数名只能访问第二个参数,要访问第一个参数必须通过arguments对象。 在严格模式下,arguments对象的行为也有所不同,在非严格模式下,修改明明参数的值也会反应到arguments对象中,而严格模式下这两个值是完全独立的。如:

COPYJAVASCRIPT

// 修改命名参数的值 // 非严格模式:修改会反应到arguments中 // 严格模式:修改不会反应到arguments中 function doSomething(value){ value = 7; console.log(value, arguments[0]); // 非严格模式下,输出:7, 7 // 严格模式下,输出:7, 10 } doSomething(10);

另一个变化是淘汰了arguments.callee和arguments.caller。在非严格模式下,这两个属性一个引用函数本身,一个引用调用函数。而在严格模式下,访问哪个属性都会抛出TypeError。例如:

COPYJAVASCRIPT

// 访问arguments.callee // 非严格模式:正常 // 严格模式:抛出错误 function factorial(num){ if(num<=) return 1; return num*arguments.callee(num-1); } var result = factorial(4);

与变量类似,严格模式对函数名也作出了限制,不允许使用implements, interface, protected, public, staticyield作为函数名。 对函数的最后一点限制,就是只能在脚本的顶级和在函数内部声明函数。而在if语句中声明函数与导致语法错误:

COPYJAVASCRIPT

if(true){ function doSomething(){ // ... } }

在非严格模式下,以上代码在所有的浏览器上都能运行;而严格模式下会导致语法错误。

5. eval()

饱受诟病的eval()在严格模式下也得到了提升。最大的变化就是它在包含上下文中不再创建变量或函数。例如:

COPYJAVASCRIPT

// 使用eval()创建变量 // 非严格模式:弹出对话框显示10 // 严格模式:抛出错误 function doSomething(){ eval("x=10"); alert(x); }

如果在非严格模式下,以上代码在函数中会创建一个局部变量x,然后alert(),还会显示该变量的值。但在严格模式下,在doSomething()函数调用eval()不会创建变量x,因此调用alert()会导致抛出错误,因为x没有定义。 可以在eval()中声明变量和函数,但这些变量或函数只能在被求值的特殊作用域中有效,随后就将被销毁。

6. 其他变化

严格模式还有其他一些变化,希望能够注意。首先是抛弃了with语句。非严格模式下的with能够改变解析变支付的路径,但在严格模式下,with被简化掉了。因此,在严格模式使用with会导致语法错误。

COPYJAVASCRIPT

// with语句 // 非严格模式:允许 // 严格模式:抛出错误 with(location){ alert(href); }

严格模式下也去掉了Javascript中的八进制字面量。以0开头的八进制字面量经常会导致很多错误。在严格模式下,八进制字面量已经成为了无效的语法了。

COPYJAVASCRIPT

// 使用八进制字面量 // 非严格模式:值为8 // 严格模式:抛出语法错误 var value = 010;

ES5也修改了严格模式下parseInt()的行为。如今,八进制字面量在严格模式下会被当做以0开头的十进制字面量。例如:

COPYJAVASCRIPT

// 使用parseInt()解析八进制字面量 // 非严格模式:值为0 // 严格模式:值为10 var value = parseInt("010");
标签:
阅读(470)

公众号:

qrcode

微信公众号:前端小茶馆

公众号:

qrcode

微信公众号:前端小茶馆