ECMAScript5的strict mode在javascript中是一种限制变量的一种方式。strict mode 不仅仅是一个子集:它的本意就是从正常的代码中有不同的语意。不支持严格模式的浏览器运行严格模式下的代码将有不同的行为,所以不要依靠没有功能测试支持相关方面的严格模式.
另外,严格模式和非严格模式的代码可以共存,所以脚本可以选择严格模式。
严格模式较正常的JavaScript语义有几项变动:
首先,严格模式通过抛出错误消除了一些JavaScript静态的错误。
其次,严格模式修复了javascript引擎优化实现困难的问题,严格模式经常使得代码运行的比非严格模 式下的代码更快。
第三,严格模式禁止一些语法可能在ECMAScript的未来版本中定义。
Invoking strict mode
严格模式使用于整个script或者私有方法,并不作用于用{}围起来的代码片段(非function)尝试应用于这样的环境并没有eval代码,功能函数,事件处理程序的属性,字符串传入setTimeout等整个脚步加载完成,并调用严格模式按照预期运行。
Strict mode for scripts
让整个script使用严格模式,就需要把语句"use strict"放在所以声明的前面,
// Whole-script strict mode syntax "use strict"; var v = "Hi! I'm a strict mode script!";
Strict mode for functions
同样的,为一个function启用严格模式也是将语句"use strict"放在所以声明的前面,
同样的,为一个function启用严格模式也是将语句"use strict"放在所以声明的前面, function strict(){ // Function-level strict mode syntax 'use strict'; function nested() { return "And so am I!"; } return "Hi! I'm a strict mode function! " + nested(); } function notStrict() { return "I'm not strict."; }
Changes in strict mode
严格模式改变了语法和运行时行为,改变的设计如下几个方面:改转换异常为错误,简化特定变量,简化了eval和arguments。这些改变可以让你的javascript代码更加安全,也预示着ECMAScript未来的变化。
下面一一介绍变化的方面:
Converting mistakes into errors
严格模式让提前可以接受的错误变成脚步无法运行的错误。对javascript初学者来说变得容易得多了,并且有时候给出的操作为错误而非语意错误。我们经常修复中级别的错误,但是还会给未来造成更严重的错误。严格模式视这些错误为error级别的提示开发者可以发现并且及时修复。
首先,严格模式可以让你不会意外地声明一个全局变量。在原生的javascript中定义变量不完整就可以让这个变量暴露在了全局中并且还能运行。这时你就可以把代码撇到严格模式中。
"use strict"; mistypedVaraible = 17; // this line throws a ReferenceError due to the mispelling of variable
第二,严格模式使得内存分配默默地消失抛出一个异常。例如,NaN是个全局的不可写的变量,通常我们不能给NaN设置值,开发者不会得到错误反馈。在严格模式中给NaN设置值会抛出一个异常。在原生js中任何给不可写的元素赋值,给只有get方法的元素赋值和给不可扩展的属性赋值都是隐含的错误,这样还是放在严格模式里面比较好。如下:
"use strict"; // Assignment to a non-writable property var obj1 = {}; Object.defineProperty(obj1, "x", { value: 42, writable: false }); obj1.x = 9; // throws a TypeError // Assignment to a getter-only property var obj2 = { get x() { return 17; } }; obj2.x = 5; // throws a TypeError // Assignment to a new property on a non-extensible object var fixed = {}; Object.preventExtensions(fixed); fixed.newProp = "ohai"; // throws a TypeError
第三,严格模式使得试图删除对象内置的属性时依然会报typeerror。如下:
"use strict"; delete Object.prototype; // throws a TypeError
第四,严格模式要求声明到对象中属性是唯一的。在原生的js中对象中的属性是可以重复的,最后一个声明的属性值会覆盖在原来声明的属性值。如果只是改变对象的属性而不是改变改变最后一个实例的话,重复只是一种错误的实现,因为最后一个属性就能做任何事情。重复的属性在严格模式中会提示错误。
"use strict"; var o = { p: 1, p: 2 }; // !!! syntax error
第五,严格模式要求function的参数名称是唯一的。在非严格模式下重复的参数会隐藏掉前面的参 数, 之前的仍然通过arguments[i]进行访问。
function sum(a, a, c){ // !!! syntax error "use strict"; return a + b + c; // wrong if this code ran }
第六,严格模式禁止8进制数据(即015形式)(8进制不是ECMAScript规范的一部分)
"use strict"; var sum = 015 + // !!! syntax error 197 + 142;
Simplifying variable uses
严格模式简化了变量名在代码中的定义,许多的编译器优化依赖变量所在的位置,这个对于javascript的系统优化是很关键的。首先,严格模式禁止with的使用(不推荐使用的不再相信介绍,只是描述下而已),因为with非常不利于优化。
"use strict"; var x = 17; with (obj) // !!! syntax error { x;}
并且严格模式下,传入eval的代码不能在调用程序所在的上下文定义属性和方法,在非严格模式下是可以这么做的。相反,变量和函数的定义是在eval创建新的作用域中这个作用域就不再使用了。
Making eval and arguments simpler
首先,eval和arguments都不能被绑定和赋值,下面所有的情况都是语法错误:
"use strict"; eval = 17; arguments++; ++eval; var obj = { set p(arguments) { } }; var eval; try { } catch (arguments) { } function x(eval) { } function arguments() { } var y = function eval() { }; var f = new Function("arguments", "'use strict'; return 17;");
第二,严格模式下arguments不能起别名,在非严格模式下参数是arg的function,如果是给arg赋值,同样会修改arguments[0],反之亦然。在严格模式中,如果方法别调用,function会存储最原始的arguments对象,arguments[i]不在绑定对应的命名参数,请看下面的例子:
function f(a){ "use strict"; a = 42; return [a, arguments[0]]; } var pair = f(17); console.info(pair[0] === 42); console.info(pair[1] === 17);
第三,arguments.callee不在支持
"use strict"; var f = function() { return arguments.callee; }; f(); // throws a TypeError
"Securing" JavaScript
严格模式使得可以轻松地写安全的javascript代码,有些网站现在提供的方式是为用户编写JavaScript将通过在网站上代表其他用户运行,javascript可以访问到用户的一些隐私信息,所以很多的js代码 运行请做一定的转换,检查一些功能的可访问性,javascript的灵活性使得这种改变很简单。
首先,在严格模式下做为this的引用给函数传值的时候不再强制要求是个object,在非严格模式下的function中,this通常是一个对象:如果使用对象调用,this就被包装成对象,如果使用Boolean,string,nubmer 去调用this就会被包装成对应的值。不止自动包装会有性能损失,并且暴露到公共的环境中也是有风险的。安全的代码必须是有所限制的。对应一个严格模式下的function,就算是指定了this的值,也不会被包装。如果没有指定就会是undefined。
"use strict"; function fun() { return this; } console.info(fun() === undefined); console.info(fun.call(2) === 2); console.info(fun.apply(null) === null); console.info(fun.call(undefined) === undefined); console.info(fun.bind(true)() === true);
console.info
也就是说,在严格模式中,this不在指向了window对象,非严格模式下的this可以参考我的另一篇博文 http://hcc0926.blog.51cto.com/172833/1562179
后面是不怎么常用的点,需要的可以看原文。
原文地址:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
参考资料:javascript权威指南第六版