ES5 规范之严格模式详解

前言

ECMAScript 5 最先引入了 “严格模式”(strict mode)的概念。经过严格模式,能够在函数内部存在的错误,及时捕获一些可能致使编程错误的 ECMAScript 行为。javascript

理解严格模式的规则很是重要,ECMAScript 的下一个版本将以严格模式为基础制定。支持严格模式的浏览器包括 IE10+、Firefox 4+、Safari 5.1+ 和 Chrome。java

严格模式的目的

  • 消除 JavaScript 语法的一些不合理、不严谨之处,减小一些怪异行为
  • 消除代码运行的一些不安全之处,保证代码运行的安全
  • 提升编译器效率,增长运行速度
  • 为将来新版本的 JavaScript 作好铺垫

严格模式的开启

想要开启严格模式,直接在做用域开始的位置写上字符串 "use strict";编程

在全局模式下开启:浏览器

"use strict";
复制代码

在局部模式下开启(在函数中打开严格模式):安全

function fn(){
 "use strict";
     // 其余代码
}
复制代码

严格模式的规则(执行限制)

一、变量var:消除了伪全局变量

在严格模式下,何时建立变量以及怎么建立变量都是有限制的。不容许意外建立全局变量(就是严格模式下消除了伪全局变量)。了解伪全局变量请阅读【三分钟带你深刻理解 JavaScript 的函数做用域markdown

// 注意:(function(){})()是一个匿名函数
(function () { 
    a = 10;
    console.log(a);
})(); // 结果:10

(function () {
 "use strict";
    a = 10;
})();  // 报错:ReferenceError: a is not defined
复制代码

在非严格模式下,即便变量 a 前面没有 var 关键字,即便没有将它定义为某个全局对象的属性,也能将 a 建立为伪全局变量使用。dom

在严格模式下,若是给一个没有声明的变量赋值,那代码在执行的时候就会抛出错误 ReferenceError(引用错误)函数

二、对函数参数的要求:更为严格

严格模式要求命名函数的参数必须惟一。post

// 非严格模式
(function () { 
    function foo(a ,a, b){
         console.log(a,b);
     }
    foo(1,2,3)
 })();  // 结果: 2 3

// 严格模式
 (function () { 
 "use strict";
     function foo(a ,a, b){
         console.log(a,b);
     }
     foo(1,2,3)
 })(); // 报错:SyntaxError: Duplicate parameter name not allowed in this context
复制代码

在非严格模式下,这个函数声明不会抛出错误。经过参数名只能访问重复参数的第二个参数,要访问第一个重复参数,必须经过 arguments 对象。ui

在严格模式下,上面函数参数的不规范会抛出 SyntaxError(对象表明尝试解析语法上不合法的代码的错误)

三、实参形参 和 arguments 的分离

在严格模式下,arguments对象的行为有所不一样。

在非严格模式下,修改命名参数的值也会反映到 arguments 对象中,而严格模式下这两个值是彻底独立的。

// 非严格模式
// arguments 会受到 形参赋值的影响;
(function(){
    function foo(a,b){
        a = 20;
        console.log(a,b);  // 20 2
        console.log(arguments[0],arguments[1]); // 20 2
    }
    foo(1,2)
})(); 

// 严格模式
(function(){
 "use strict";
    // 形参 和 arguments 之间的区别;
    // 形参是变量能够随意赋值;
    // arguments 就是对应实参的关键字获取全部的实参,进行使用,不会被改变;
    function foo(a,b){
        a = 20;
        console.log(a,b);  // 20, 2 
        console.log(arguments[0],arguments[1]);  // 1, 2 
    }
    foo(1,2)
})();
复制代码

以上代码中,函数 foo() 传入两个参数 a,b 。调用这个函数时传入了两个参数“1,2”,这个值赋个了对应的变量。而在函数内部,a 的值被修改成“20”。

在非严格模式下,这个修改的值也会改变 arguments[0] 的值; 但在严格模式下,arguments[0] 的值仍然是传入的值。

四、arguments 的严格使用,部分功能禁用了

淘汰了 arguments.calleearguments.caller。 在非严格模式下,这两个属性一个是引用函数自己,一个是引用调用函数。而在严格模式下,这两个属性都被禁用了。

(function(){
    function foo(){
       // arguments.callee 指向了当前的函数自己;
       console.log(arguments.callee);
    }
    foo()
})();  // 结果: ƒ foo(){console.log(arguments.callee);}

(function(){
 "use strict";
    function foo(){
       // 禁用掉了大部分arguments的属性;
       console.log(arguments.callee)
    }
    foo()
})();  // 报错:TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments
复制代码

相似的,尝试读写函数的 caller 属性也会抛出 TypeError(类型错误)。本身能够尝试一下呦!

五、严格模式之中对 this 的严格(抑制this

JavaScript 中一个最大的安全问题,也是最容易让人迷惑的地方就是在某些状况下如何抑制this的值。

在非严格模式下,nullundefined 值会被转换为全局对象 window。而在严格模式下,函数的 this 值始终是指定的值,不管指定的是什么值。

(function(){
    function foo(){
        // this 指向 window;
       console.log(this);
    }
    foo()
})(); // 结果:Window 

(function(){
 "use strict";
    function foo(){
        // 禁用指向了 window 的 this,让 this 指向 undefined
       console.log(this);
    }
    foo()
})();  // 结果:undefined
复制代码

在之后的编程之中,this 最没有用的指向就是全局对象 window

六、禁用 with(){} 语句

在非严格模式下的 with 语句可以改变解析标识符的路径,但在严格模式下,with 被抛弃了。所以,在严格模式下使用 with 会致使语法错误。

(function(){    
    with(Math){
        // 能够省略对象前置;
        console.log(random()); // => Math.random()
        console.log(PI);  // => Math.PI
    }
})();  

// 严格模式之下禁用 with(){}
(function(){
 "use strict";
    with(Math){
        console.log(random());
        console.log(PI);
    }
})();  // 报错:Uncaught SyntaxError: Strict mode code may not include a with statement
复制代码

在非严格模式下,with能够改变做用域链,他可让他里面的代码的做用域链的最顶端变成 with 括号里面的这个对象。做用域链是通过很复杂的状况生成的结构,做用域链改了以后,系统内核会消耗大量的效率去更改做用域链,是会把程序变得很是慢的。因此 ES5 的严格模式为了提升效率,禁用 with 语句。

七、在严格模式之中被禁用的进制:不容许使用八进制

以 0 开头的八进制字面量过去常常会致使不少错误,在严格模式下,八进制字面量已经成为无效的语法了。

(function(){
    // 0 开头就是八进制的标志;
    console.log(012);
})(); // 结果: 10 (自动转化成十进制)

(function(){
 "use strict"
    console.log(012)
})(); //报错:Uncaught SyntaxError: Octal literals are not allowed in strict mode.
复制代码
补充:ES5 也修改了严格模式下的 parseInt() 的行为。现在八进制的字面量在严格模式下会被看成以 0 开头的十进制字面量。例如:
(function(){
    var value = 012;
    console.log(value);
 })(); // 结果: 10 

 (function(){
 "use strict";
    var value = parseInt("012");
    console.log(value); 
 })(); // 结果: 12 
复制代码

若是对您有帮助,欢迎点赞关注;文章若有遗漏之处欢迎评论区留言讨论。

相关文章
相关标签/搜索