ECMAScript 5严格模式(Strict Mode)介绍

  严格模式(Strict Mode)是ECMAScript 5的新特性,它允许你把整个程序,或者某个函数,放置在“严格”的操作语境中。这种严格的语境会防止某些特定的操作并抛出更多的异常。

  虽然ECMAScript 5对ECMAScript 3是向下兼容的,但是在严格模式下,所有在ECMAScript 3中不赞成使用的特性都被禁用(或抛出错误)而不是兼容。

  启用严格模式有以下好处:

  1.捕获一些编程错误,并抛出异常。

  2.阻止进行一些相对“不安全”的操作(例如访问全局变量),抛出异常。

  3.禁用一些让人迷惑的特性。

  关于严格模式的大多数信息都可以在《ES5规范》[PDF]的第223页找到。

  (注意:ECMAScript 5的严格模式跟Firefox的严格模式是不同的)

  如何启用严格模式

  在程序的开头添加这条语句即可对整段脚本启用严格模式:

  

复制代码 代码如下:

  'use strict';

  也可以只在函数的内部启用严格模式,这样不会影响到外部:

  

复制代码 代码如下:

  function imStrict() {

  'use strict';

  // ... your code ...

  }

  启用严格模式的语句只是一段普通的字符串“use strict”,没有任何新语法。这意味着不会对就旧式浏览器造成任何负面影响。

  在函数内部启用严格模式的一个实际应用是,把整个Javascript类库定义在严格模式的函数内部,这样就可以不影响外部的代码:

  

复制代码 代码如下:

  // Non-strict code...

  (function(){

  "use strict";

  // Define your library strictly...

  })();

  // Non-strict code...

  那么,严格模式下的脚本有什么改变呢?

  变量和属性

  对未定义变量的赋值将会失败,而不是把这个变量作为全局变量。

  写入一个可写特性为false的属性,删除一个可配置特性为false的属性,或者添加一个可扩展特性为false的属性,都会导致错误(这些特性是预先商定好的)。过去,这些操作不会抛出异常,仅仅是静默地失败。

  对变量、函数或者函数参数执行delete操作会导致错误。

  

复制代码 代码如下:

  var foo = 'test';

  function test() { }

  delete foo; // Error

  delete test; // Error

  function test2(arg) {

  delete arg; // Error

  }

  在一个对象容器内部定义相同属性会导致异常的抛出:

  

复制代码 代码如下:

  // Error

  { foo: true, foo: false }

  eval

  任何对“eval”这个名字的使用(主要意图是把eval函数指向一个变量或者是对象的属性)都是禁止的。

  

复制代码 代码如下:

  // All generate errors...

  obj.eval = ...

  obj.foo = eval;

  var eval = ...;

  for ( var eval in ... ) {}

  function eval(){}

  function test(eval){}

  function(eval){}

  new Function("eval")

  另外,通过eval声明新变量也会无效:

  

复制代码 代码如下:

  eval("var a = false;");

  print( typeof a ); // undefined

  函数

  重写arguments对象会导致错误:

  

复制代码 代码如下:

  arguments = [...]; // not allowed

  同名参数会导致错误:

  

复制代码 代码如下:

  (function(foo, foo) { }) // Error

  对arguments.caller和arguments.callee的访问会抛出异常。因此,任何需要用到的匿名函数都必须先命名,例如:

  

复制代码 代码如下:

  setTimeout(function later(){

  // do stuff...

  setTimeout(later, 1000);

  }, 1000 );

  函数的arguments、caller和callee属性不再存在,定义它们的操作也是禁止的。

  

复制代码 代码如下:

  function test() { }

  test.caller = 'caller';  // Error

  最后,一个长期存在(且非常讨厌)的BUG已经被解决了:当使用null或者undefined作为Function.prototype.call或Function.prototype.apply方法的第一个参数时,函数内部的this将会指向全局对象。而严格模式将会阻止其执行并抛出异常:

  

复制代码 代码如下:

  (function(){ ... }).call(null); // Exception

  with() { }

  with() { }语句在严格模式下是完全挂掉了。