概述

ECMAScript 5的严格模式是JavaScript中的一种限制性更强的变种方式。严格模式不是一个子集:它在语义上与正常代码有着明显的差异。不支持严格模式的浏览器与支持严格模式的浏览器行为上也不一样, 所以不要在未经严格模式特性测试情况下使用严格模式。严格模式可以与非严格模式共存,所以脚本可以逐渐的选择性加入严格模式。

严格模式在语义上与正常的JavaScript有一些不同。 首先,严格模式会将JavaScript陷阱直接变成明显的错误。其次,严格模式修正了一些引擎难以优化的错误:同样的代码有些时候严格模式会比非严格模式下更快。 第三,严格模式禁用了一些有可能在未来版本中定义的语法。

如果你想让你的JavaScript代码在严格模式下运行,可以参考转换成严格模式

开启严格模式

作用于整个脚本文件

需要在所有语句之前放一个特定语句 "use strict"; (或 'use strict';)注意必须是脚本开始第一行,否则无效

// 整个语句都开启严格模式的语法
"use strict";
var v = "Hi!  I'm a strict mode script!";

合并不同模式的代码文件成一个文件,需要特别注意:
这种语法存在陷阱,有一个大型网站已经被它坑倒了:不能盲目的合并冲突代码。试想合并一个严格模式的脚本和一个非严格模式的脚本:合并后的脚本代码看起来是严格模式。反之亦然:非严格合并严格看起来是非严格的。合并均为严格模式的脚本或均为非严格模式的都没问题,只有在合并严格模式与非严格模式有可能有问题。建议按一个个函数去开启严格模式(至少在学习的过渡期要这样做)

作用于单个函数

同样讲'use strict';置于函数开始的第一行
测试生效:

!function(){
    'use strict';
    x=1;
    console.log(x);    //因严格模式不允许未声明的变量被赋值,会报错
}();

报错信息:

$ node 严格模式.js
D:\js\严格模式.js:3
        x=1;
         ^

ReferenceError: x is not defined

如果不是放在第一行没有进入严格模式,结果会是1

严格模式有哪些不同

  • 不允许未声明的变量被赋值(见上例)

  • 将拼写错转成异常

    "use strict";
    // 假如有一个全局变量叫做mistypedVariable
    mistypedVaraible = 17; // 因为变量名拼写错误,这一行代码就会抛出 ReferenceError
  • 在严格模式下, 试图删除不可删除的属性时会抛出异常(之前这种操作不会产生任何效果):

    "use strict";
    delete Object.prototype; // 抛出TypeError错误
  • 对象字面量重复属性名报错
    正常模式下重名属性是允许的,最后一个重名的属性决定其属性值。因为只有最后一个属性起作用,当代码是要改变属性值而却不是修改的最后一个重名属性的时候,复制这个对象就产生一连串的bug。在严格模式下,重名属性被认为是语法错误:

    "use strict";
    var o = { p: 1, p: 2 }; // !!! 语法错误
  • 严格模式禁止八进制数字语法.
    测试如下:

    !function(){
        console.log(0123);                //八进制字面量不被允许
    }();

    报错信息如下:

    $ node 严格模式.js
    D:\js\严格模式.js:19
            console.log(0123);                //八进制字面量不被允许
                        ^^^^
    SyntaxError: Octal literals are not allowed in strict mode.
    
  • 禁止使用with语句
    因为with语句无法在编译时就确定,属性到底归属哪个对象。严格模式下, 使用 with 会引起语法错误, 所以就不会存在 with 块内的变量在运行是才决定引用到哪里的情况了

    "use strict";
    var x = 17;
    with (obj) // !!! 语法错误
    {
      // 如果没有开启严格模式,with中的这个x会指向with上面的那个x,还是obj.x?
      // 如果不运行代码,我们无法知道,因此,这种代码让引擎无法进行优化,速度也就会变慢。
      x;
    }
  • eval 独立作用域
    在严格模式下 eval 仅仅为被运行的代码创建变量,eval作用域内不再能够生成全局变量了,它所生成的变量只能用于eval内部。

    var x = 17;
    var evalX = eval("'use strict'; var x = 42; x");
    console.log(x === 17);        //true
    console.log(evalX === 42);        //true
  • 严格模式禁止删除声明变量。delete name 在严格模式下会引起语法错误:

    "use strict";
    
    var x;
    delete x; `// !!! 语法错误
  • this不再指向全局对象
    一个开启严格模式的函数,指定的this不再被封装为对象,而且如果没有指定this的话它值是undefined

    function fun() { return this; }
    console.log(fun() === undefined);    //true
    console.log(fun.call(2) === 2);        //true
    console.log(fun.apply(null) === null);        //true
    console.log(fun.call(undefined) === undefined);        //true
    console.log(fun.bind(true)() === true);        //true
  • arguments变为参数的静态副本
    严格模式下,函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。

    function f(a)
    {
      "use strict";
      a = 42;
      return [a, arguments[0]];
    }
    var pair = f(17);
    console.log(pair);    //[ 42, 17 ]

参考资料

MDN文档
阮一峰老师的博客


已注销
958 声望58 粉丝