分享

Javascript

 复杂网络621 2015-08-01

为了使Javascript代码更加严谨,在EMCAScript 5添加了一种新的模式 -strict mode,也就是常说的严格模式。严格模式是与正常模式比较而言的。

开启 Strict 模式

开启strict模式用一句话就可以实现:

"use strict";

但面临的问题是这个strict模式起作用的范围有多大。当我们在一个脚本的第一行加上这个语句,那么这个脚本都会处于strict模式下。

<script>"use strict";...

但是这会面临一个问题,如果拼合严格模式和正常模式的脚本可能导致整个代码混论不堪,与严格模式的初衷相悖,所以对整个脚本实行严格模式时需要相当谨慎,部署严格模式的脚本到整个项目中要考虑拼接的结果。

还有一种比较安全的方法就是函数中使用strict模式,当然也要在函数体内的第一行。

function() {"use strict";...}

此时严格模式只在函数体内生效,这会比脚本生效更加安全。

Strict 模式的具体表现

1.全局变量

strict模式下,不可以给一个未声明的全局变量赋值:

<script>"use strict";a = 1;</script>

此时会抛出错误:

Uncaught ReferenceError: a is not defined 

2.不可写变量

今天在博文-《细说 Javascript 拾遗篇(二) : undefined 和 null》已经确定了在EMCAScript全局变量undefined属性是不可重写,虽然不可重写,但在正常模式下赋值并不会报错,但是在strict模式如果对不可写变量赋值将会报错:

<script>"use strict";undefined = 123;</script>

此时会抛出错误:

Uncaught TypeError: Cannot assign to read only property 'undefined' of [object Object] 

3.删除机制

在正常模式下删除不可删除的变量或属性时并不会报错(对于删除变量会返回false),然而在strict模式下删除不可删除的变量货属性时则是不可行的,因为为报错。

<script>"use strict";var a = 1;delete a;</script>

此时会抛出错误:

Uncaught SyntaxError: Delete of an unqualified identifier in strict mode. 

4.命名的唯一性

对于strict模式下,函数的参数和对象内的变量都不能有重命名现象。
而在正常模式下是允许的。

<script>"use strict";function foo(a, a) {return a*a;}</script>

此时会抛出错误:

Uncaught SyntaxError: Strict mode function may not have duplicate parameter names 

5.八进制的支持

strict模式不支持数字的八进制表示,我们知道在正常模式下,第一位为的数字将会认为是八进制,但是在strict模式不允许。

<script>"use strict";var a = 01;</script>

此时会抛出错误:

Uncaught SyntaxError: Octal literals are not allowed in strict mode. 

6.with 语句

Javascriptstrict模式很重要的一个改变就是变量在编译阶段就已经确定,这与正常模式下允许运行时确定变量有很大的不同。这对Javascript代码的优化作用很大。

因此with语句在strict模式下是不被支持的,因为我们都知道with语句只有在运行时才能确定变量。

<script>"use strict";var obj = {a:1};with(obj) {var b = a;}</script>

此时会抛出错误:

Uncaught SyntaxError: Strict mode code may not include a with statement 

7.eval 函数作用域

正常模式下,eval函数在哪个作用域下执行就属于哪个作用域,例如在全局作用域下执行则属于全局作用域,但在strict模式下,eval函数拥有自己的作用域。

<script>"use strict";var a = 1;eval('var a = 2');console.log(a);</script>

正常模式下输出为: 2。
strict模式下输出为 1。

此外,strict模式下,不可以对eval赋值。

<script>"use strict";eval = 1;</script>

此时会抛出错误:

Uncaught SyntaxError: Unexpected eval or arguments in strict mode 

8.arguments 对象

strict模式下对函数的额arguments对象做了很大的限制。
首先,argumentseval一样,不可被赋值。

<script>"use strict";arguments = 1;</script>

此时会抛出错误:

Uncaught SyntaxError: Unexpected eval or arguments in strict mode 

其次,不再动态追踪函数的参数。

<script>"use strict";function foo(a) {a = 2;return arguments[0];}console.log(foo(1));</script>

正常模式下输出为: 2。
strict模式下输出为 1。

最后,strict模式不再支持arguments.callee的使用。

9.函数体内的 this

在正常模式下,我们都知道函数体内的this将指向全局对象,然而在strict模式下,this不仅不会指向全局对象,而且在函数定义体内直接使用还会报错,只有在使用new创建新对象实例时才可以使用this,而且指向的是新的对象实例,并非全局对象。

<script>"use strict";var a = 1;function foo() {console.log(this.a);}foo();</script>

此时会抛出错误:

Uncaught TypeError: Cannot read property 'a' of undefined 

10.函数体内访问调用栈

strict模式下,函数体内不再运行访问调用栈,所以下例会报错:

<script>"use strict";function foo() {foo.callee;foo.caller;foo.arguments;}foo();</script>

此时会抛出错误:

Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them 

11.函数声明的位置

在正常模式下,函数声明可以在任何位置,然后再strict模式下,必须在全局作用域或函数作用域的顶端声明函数。

<script>"use strict";var a = 1;if(a === 1) {function foo() {}}</script>

此时会抛出错误:

Uncaught SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function

总结

阅读完MDNstrict模式的阐述,不仅能看出strict模式是对Javascript代码规范性所起到的作用,同时也能看出这也为了新规范新版本的Javascript功能做好了铺垫,例如最后一个在函数声明位置上的表现,能够看出浓浓的块级作用域的想法。所以建议大家在书写Javascript代码时尽量以strict模式规范自己的代码。

参考

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/Strict_mode

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多