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

前言

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

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

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

  • 消除 JavaScript 語法的一些不合理秒拔、不嚴(yán)謹(jǐ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)格模式下庵芭,什么時候創(chuàng)建變量以及怎么創(chuàng)建變量都是有限制的。不允許意外創(chuàng)建全局變量(就是嚴(yán)格模式下消除了偽全局變量)

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

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

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

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)
         })(); // 報錯:SyntaxError: Duplicate parameter name not allowed in this context

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

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

3版扩、實參形參 和 arguments 的分離

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

       // 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)實參的關(guān)鍵字獲取所有的實參柿扣,進(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() 傳入兩個參數(shù) a析桥,b 司草。調(diào)用這個函數(shù)時傳入了兩個參數(shù)“1艰垂,2”,這個值賦個了對應(yīng)的變量埋虹。而在函數(shù)內(nèi)部猜憎,a 的值被修改為“20”。

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

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

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

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

        (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()
        })();  // 報錯:TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments

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

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

JavaScript 中一個最大的安全問題窗悯,也是最容易讓人迷惑的地方就是在某些情況下如何抑制 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)致語法錯誤鲫尊。

        (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);
            }
        })();  // 報錯:Uncaught SyntaxError: Strict mode code may not include a with statement

在非嚴(yán)格模式下,with可以改變作用域鏈沦偎,他可以讓他里面的代碼的作用域鏈的最頂端變成with括號里面的這個對象疫向,作用域鏈?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)致很多錯誤堆巧,在嚴(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)
        })(); //報錯:Uncaught SyntaxError: Octal literals are not allowed in strict mode.
補充: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)系作者
  • 序言:七十年代末荒揣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子焊刹,更是在濱河造成了極大的恐慌系任,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虐块,死亡現(xiàn)場離奇詭異俩滥,居然都是意外死亡,警方通過查閱死者的電腦和手機贺奠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門霜旧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人儡率,你說我怎么就攤上這事挂据。” “怎么了儿普?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵崎逃,是天一觀的道長。 經(jīng)常有香客問我眉孩,道長个绍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任浪汪,我火速辦了婚禮障贸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吟宦。我一直安慰自己篮洁,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布殃姓。 她就那樣靜靜地躺著袁波,像睡著了一般瓦阐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篷牌,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天睡蟋,我揣著相機與錄音,去河邊找鬼枷颊。 笑死戳杀,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的夭苗。 我是一名探鬼主播信卡,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼题造!你這毒婦竟也來了傍菇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤界赔,失蹤者是張志新(化名)和其女友劉穎丢习,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淮悼,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡咐低,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了袜腥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片见擦。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瞧挤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情儡湾,我是刑警寧澤特恬,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站徐钠,受9級特大地震影響癌刽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尝丐,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一显拜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧爹袁,春花似錦远荠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽档址。三九已至,卻和暖如春邻梆,著一層夾襖步出監(jiān)牢的瞬間守伸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工浦妄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尼摹,地道東北人。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓剂娄,卻偏偏與公主長得像蠢涝,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宜咒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容