ES5 規(guī)范之嚴(yán)格模式詳解

前言

ECMAScript 5最早引入了“嚴(yán)格模式”(strict mode)的概念。通過嚴(yán)格模式,可以在函數(shù)內(nèi)部存在的錯(cuò)誤,及時(shí)捕獲一些可能導(dǎo)致編程錯(cuò)誤的ECMAScript 行為。

理解嚴(yán)格模式的規(guī)則非常重要,ECMAScript的下一個(gè)版本將以嚴(yán)格模式為基礎(chǔ)制定。支持嚴(yán)格模式的瀏覽器包括IE10+、Firefox 4+、Safari 5.1+和Chrome。

嚴(yán)格模式的目的

  • 消除 JavaScript 語法的一些不合理、不嚴(yán)謹(jǐn)之處,減少一些怪異行為
  • 消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全
  • 提高編譯器效率,增加運(yùn)行速度
  • 為未來新版本的 JavaScript 做好鋪墊

嚴(yán)格模式的開啟

想要開啟嚴(yán)格模式,直接在作用域開始的位置寫上字符串 "use strict";

在全局模式下開啟:

"use strict";

在局部模式下開啟(在函數(shù)中打開嚴(yán)格模式):

function fn(){
    "use strict";
    // 其他代碼
}

嚴(yán)格模式的規(guī)則(執(zhí)行限制)

1、變量 var:消除了偽全局變量

在嚴(yán)格模式下,什么時(shí)候創(chuàng)建變量以及怎么創(chuàng)建變量都是有限制的。不允許意外創(chuàng)建全局變量(就是嚴(yán)格模式下消除了偽全局變量)

// 注意:(function(){})()是一個(gè)匿名函數(shù)
        (function () { 
            a = 10;
            console.log(a);
        })(); // 結(jié)果:10
        
        (function () {
            "use strict";
            a = 10;
        })();  // 報(bào)錯(cuò):ReferenceError: a is not defined

在非嚴(yán)格模式下,即使變量 a 前面沒有 var 關(guān)鍵字,即使沒有將它定義為某個(gè)全局對象的屬性,也能將 a 創(chuàng)建為偽全局變量使用。

在嚴(yán)格模式下,如果給一個(gè)沒有聲明的變量賦值,那代碼在執(zhí)行的適合就會拋出 ReferenceError(引用錯(cuò)誤)

2、對函數(shù)參數(shù)的要求:更為嚴(yán)格

嚴(yán)格模式要求命名函數(shù)的參數(shù)必須唯一

        (function () { 
            function foo(a ,a, b){
                 console.log(a,b);
             }
            foo(1,2,3)
         })();  // 結(jié)果: 2 3
         
         (function () { 
             "use strict";
             function foo(a ,a, b){
                 console.log(a,b);
             }
             foo(1,2,3)
         })(); // 報(bào)錯(cuò):SyntaxError: Duplicate parameter name not allowed in this context

在非嚴(yán)格模式下,這個(gè)函數(shù)聲明不會拋出錯(cuò)誤。通過參數(shù)名只能訪問重復(fù)參數(shù)的第二個(gè)參數(shù),要訪問第一個(gè)重復(fù)參數(shù),必須通過arguments對象(請見下一條)。

在嚴(yán)格模式下,上面函數(shù)參數(shù)的不規(guī)范會拋出 SyntaxError(對象代表嘗試解析語法上不合法的代碼的錯(cuò)誤)

3、實(shí)參形參 和 arguments 的分離

在嚴(yán)格模式下,arguments 對象的行為有所不同。在非嚴(yán)格模式下,修改命名參數(shù)的值也會反映到 arguments 對象中,而嚴(yán)格模式下這兩個(gè)值是完全獨(dú)立的。

       // 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 之間的區(qū)別;
            // 形參是變量可以隨意賦值;
            // arguments 就是對應(yīng)實(shí)參的關(guān)鍵字獲取所有的實(shí)參,進(jìn)行使用,不會被改變;
            function foo(a,b){
                a = 20;
                console.log(a,b);  // 20 , 2 
                console.log(arguments[0],arguments[1]);  //  1 , 2  
            }
            foo(1,2)
        })();

以上代碼中,函數(shù) foo() 傳入兩個(gè)參數(shù) a,b 。調(diào)用這個(gè)函數(shù)時(shí)傳入了兩個(gè)參數(shù)“1,2”,這個(gè)值賦個(gè)了對應(yīng)的變量。而在函數(shù)內(nèi)部,a 的值被修改為“20”。

在非嚴(yán)格模式下,這個(gè)修改的值也會改變 arguments[0] 的值。

但在嚴(yán)格模式下,arguments[0] 的值仍然是傳入的值。

4、arguments 的嚴(yán)格使用,部分功能禁用了

淘汰了 arguments.callee 和 arguments.caller。在非嚴(yán)格模式下,這兩個(gè)屬性一個(gè)是引用函數(shù)本身,一個(gè)是引用調(diào)用函數(shù)。而在嚴(yán)格模式下,這兩個(gè)屬性都被禁用了。

        (function(){
            function foo(){
               // arguments.callee 指向了當(dāng)前的函數(shù)本身;
               console.log(arguments.callee);
            }
            foo()
        })();  // 結(jié)果 ? foo(){console.log(arguments.callee);}
        
        (function(){
            "use strict";
            function foo(){
               // 禁用掉了大部分arguments的屬性;
               console.log(arguments.callee)
            }
            foo()
        })();  // 報(bào)錯(cuò):TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments

類似的,嘗試讀寫函數(shù)的 caller 屬性也會拋出 TypeError(類型錯(cuò)誤)。

5、嚴(yán)格模式之中對 this 的嚴(yán)格(抑制this)

JavaScript 中一個(gè)最大的安全問題,也是最容易讓人迷惑的地方就是在某些情況下如何抑制 this 的值。在非嚴(yán)格模式下,null 或 undefined 值會被轉(zhuǎn)換為全局對象window。而在嚴(yán)格模式下,函數(shù)的 this 值始終是指定的值,無論指定的是什么值。

        (function(){
            function foo(){
                // this 指向 window;
               console.log(this);
            }
            foo()
        })(); // 結(jié)果:Window 
        
        (function(){
            "use strict";
            function foo(){
                // 禁用指向了 window 的 this,讓 this 指向 undefined
               console.log(this);
            }
            foo()
        })();  // 結(jié)果:undefined

在以后的編程之中,this 最沒有用的指向就是 全局對象window。

6、禁用 with(){} 語句

在非嚴(yán)格模式下的 with 語句能夠改變解析標(biāo)識符的路徑,但在嚴(yán)格模式下,with 被拋棄了。因此,在嚴(yán)格模式下使用 with 會導(dǎo)致語法錯(cuò)誤。

        (function(){    
            with(Math){
                // 可以省略對象前置;
                console.log(random()); // => Math.random()
                console.log(PI);  // => Math.PI
            }
        })();  
        
        // 嚴(yán)格模式之下禁用 with(){}
        (function(){
            "use strict";
            with(Math){
                console.log(random());
                console.log(PI);
            }
        })();  // 報(bào)錯(cuò):Uncaught SyntaxError: Strict mode code may not include a with statement

在非嚴(yán)格模式下,with可以改變作用域鏈,他可以讓他里面的代碼的作用域鏈的最頂端變成with括號里面的這個(gè)對象,作用域鏈?zhǔn)墙?jīng)過很復(fù)雜的情況生成的結(jié)構(gòu),作用域鏈改了之后,系統(tǒng)內(nèi)核會消耗大量的效率去更改作用域鏈,是會把程序變得非常慢的。所以ES5 的嚴(yán)格模式為了提高效率,禁用 with 語句

7、在嚴(yán)格模式之中被禁用的進(jìn)制:不允許使用八進(jìn)制

以 0 開頭的八進(jìn)制字面量過去經(jīng)常會導(dǎo)致很多錯(cuò)誤,在嚴(yán)格模式下,八進(jìn)制字面量已經(jīng)成為無效的語法了。

        (function(){
            // 0 開頭就是八進(jìn)制的標(biāo)志;
            console.log(012);
        })(); // 結(jié)果: 10  (自動轉(zhuǎn)化成十進(jìn)制)
        
        (function(){
            "use strict"
            console.log(012)
        })(); //報(bào)錯(cuò):Uncaught SyntaxError: Octal literals are not allowed in strict mode.
補(bǔ)充:ES5 也修改了嚴(yán)格模式下的 parseInt() 的行為。如今八進(jìn)制的字面量在嚴(yán)格模式下會被當(dāng)作以 0 開頭的十進(jìn)制字面量。例如:
        (function(){
            var value = 012;
            console.log(value);
         })(); // 結(jié)果: 10 
         
         (function(){
            "use strict";
            var value = parseInt("012");
            console.log(value); 
         })(); // 結(jié)果: 12 
         

如有遺漏之處歡迎評論區(qū)留言。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容