一.概述

严格模式是在ECMAScript5中引入的,它是该语言的一个受限制的子集,它修正了语言的重要缺陷,并提供了健壮的查错功能和增强的安全机制。使用

1
'use strict';

进入该模式,其后续所有代码都会被解析为严格代码

二.严格模式与非严格模式区别(前三条尤为重要)

  1. 严格模式中禁止使用with语句
    with用法如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var s={
    t:{
    name:'zhuo',
    id:32434
    }
    };
    with(s.t){
    name='lingyun',
    id=565
    };

    with不是简单的做了一个代码缩写,它是在当前作用域链顶层又添加了一个新的活动对象,之后属性的查找沿着作用域链,会首先从活动对象往下找,直至全局window对象。可见恰当使用with会加快查找速度,减少输入。with的性能问题另见博客
    这种作用域链的修改是临时的,在with语句结束后,顶部对象会被销毁
    还要注意with修改作用域链只在查找时有用到,如果创建新的变量,是没有作用的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var o={};
    with(o){
    x=1;
    } //o还是没有x属性,x创建在window对象中
    var s={x:0};
    with(s){
    s.x=1;
    } //s={x:1}
    (function(){
    "use strict";
    var s={x:0};
    with(s){
    s.x=1; //Strict mode code may not include a with statement(…)
    }
    })();

    可见with提供了一种只读取,写入;但不创建属性的方法

    权威指南中写到: with语句浏览器难以优化,运行效率慢
    可见严格模式中为什么禁用with

  2. 在严格模式中,所有的变量都要先声明

    1
    2
    3
    4
    (function(){
    "use strict";
    m=0; // Uncaught ReferenceError: m is not defined(…)
    })();
  3. 在严格模式中,调用一个函数(不是方法)的this指向undefined而不是window

    1
    2
    3
    4
    var isStrict = (function(){
    "use strict";
    return this === undefined;
    });

    因此我们也有了一种判断当前javascript解释器是否支持严格模式的方法

  4. 在严格模式中,通过call或apply调用函数时,this值就是第一个参数(在非严格模式中,null和undefined会被全局对象和转换为对象的非对象值所代替)

    1
    2
    3
    4
    5
    6
    7
    8
    (function(){
    'use strict';
    var f=function(){console.log(this.name);};
    var s={name:"zhuo"};
    var name="ling";
    f.call(); //Cannot read property 'name' of undefined(…)
    //如果去掉'use strict',结果为ling,证明被window取代
    })();
  5. 在严格模式中,给只读属性赋值和给不可扩展的对象创建新成员会抛出一个类型错误异常(在非严格模式中,这些操作只是简单地操作失败,不会报错)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (function(){
    'use strict'; //加上严格之后Uncaught TypeError: Cannot assign to read only property 'x' of #<Object>(…)
    var o={};
    Object.defineProperty(o, "x", {value:1, writable:false, enumerable:true, configurable:true});
    o.x = 2;
    })();
    (function(){
    'use strict'; //Uncaught TypeError: Can't add property newp, object is not extensible(…)
    var o={p:1};
    Object.preventExtensions(o);
    //Object.seal(o);
    //Object.freeze(o);
    o.newp=2;
    })();
  6. 在严格模式中,传入eval()的代码不能在调用程序所在的上下文中声明变量或者定义函数,而在非严格模式中可以这么做。

  7. 在严格模式中,arguments对象拥有传入函数值的静态副本。在非严格模式中,arguments里的数组元素和函数参数指向同一个值的引用

  8. 在严格模式中,当delete运算法之后跟随非法标识符(比如变量,函数,函数参数)时,会报错。非严格模式中只是返回false

  9. 在严格模式中, 试图删除一个不可配置的属性会报错,非严格模式中,只是返回false

  10. 在严格模式中,一个对象直接量中定义两个同名属性会报错,而非严格模式则不会

  11. 在严格模式中,参数出现同名会报错,非严格模式中不会

  12. 在严格模式中,不允许使用八进制整数直接量,非严格中可以

    1
    2
    3
    4
    (function(){
    'use strict'; //Uncaught SyntaxError: Octal literals are not allowed in strict mode.(…)
    var e=023;
    })();
  13. 在严格模式中,eval和arguments被当作关键字

  14. 在严格模式中,限制了对调用栈的检测能力,在函数中arguments.caller和arguments.callee的访问会报错。严格模式同样具有caller和arguments属性,当访问这两个属性时会报错;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (function(){
    'use strict';
    function fun(){
    console.log(arguments.caller, arguments.callee);
    }
    function callfun(){
    fun(1,2);
    }
    callfun(); //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them(…)
    })()