JS嚴(yán)格模式

通過嚴(yán)格模式,可以在函數(shù)內(nèi)部 選擇進行較為嚴(yán)格的全局或局部的錯誤條件檢測。使用嚴(yán)格模式的好處是可以提早知道代碼中存在的錯誤,及時捕獲一些可能導(dǎo)致編程錯誤的ECMAScript行為。
支持嚴(yán)格模式的瀏覽器包括IE10+、Firefox 4+、Safari 5.1+和Chrome。

選擇使用

要選擇進入嚴(yán)格模式,可以使用嚴(yán)格模式的編譯指示:

"use strict";

這種語法可以向后兼容那些不支持嚴(yán)格模式的JavaScript引擎。支持嚴(yán)格模式的引擎會啟動這種模式,而不支持該模式的引擎就當(dāng)遇到了一個未賦值的字符串字面量,會忽略這個編譯指示。
如果是在全局作用域中(函數(shù)外部)給出這個編譯指示,則整個腳本都將使用嚴(yán)格模式。也可以只在函數(shù)中打開嚴(yán)格模式:

function doSomething(){ 
    "use strict";

    //其他代碼
}

變量

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

//未聲明變量 
//非嚴(yán)格模式:創(chuàng)建全局變量 
//嚴(yán)格模式:拋出 ReferenceError
message = "Hello world! ";

其次,不能對變量調(diào)用delete操作符。非嚴(yán)格模式允許這樣操作,但會靜默失?。ǚ祷?code>false)。 而在嚴(yán)格模式下,刪除變量也會導(dǎo)致錯誤。

//刪除變量
//非嚴(yán)格模式:靜默失敗 
//嚴(yán)格模式:拋出 ReferenceError
var color = "red"; 
delete color;

嚴(yán)格模式下對變量名也有限制。特別地,不能使用implements、interfacelet、packageprivate、protectedpublic、staticyield作為變量名。這些都是保留字。在嚴(yán)格模式下,用以上標(biāo)識符作為變量名會導(dǎo)致語法錯誤。

對象

一般來說,非嚴(yán)格模式下會靜默失敗的情形,在嚴(yán)格模式下就會拋出錯誤。
在下列情形下操作對象的屬性會導(dǎo)致錯誤:

  • 為只讀屬性賦值會拋出TypeError;
  • 對不可配置的的屬性使用delete操作符會拋出TypeError;
  • 為不可擴展的的對象添加屬性會拋出TypeError

使用對象的另一個限制與通過對象字面量聲明對象有關(guān)。在使用對象字面量時,屬性名必須唯一。例如:

//重名屬性 
//非嚴(yán)格模式:沒有錯誤,以第二個屬性為準(zhǔn) 
//嚴(yán)格模式:拋出語法錯誤
var person = { 
    name: "Nicholas", 
    name: "Greg" 
};

函數(shù)

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

//重名參數(shù) 
//非嚴(yán)格模式:沒有錯誤,只能訪問第二個參數(shù) 
//嚴(yán)格模式:拋出語法錯誤
function sum (num, num){ 
    //do something
}

在非嚴(yán)格模式下,這個函數(shù)聲明不會拋出錯誤。通過參數(shù)名只能訪問第二個參數(shù),要訪問第一個參數(shù)必須通過arguments對象。
在嚴(yán)格模式下,arguments對象的行為也有所不同。在非嚴(yán)格模式下,修改命名參數(shù)的值也會反映到arguments對象中,而嚴(yán)格模式下這兩個值是完全獨立的。

//修改命名參數(shù)的值 
//非嚴(yán)格模式:修改會反映到 arguments 中 
//嚴(yán)格模式:修改不會反映到 arguments 中
function showValue(value){
    value = "Foo";
    alert(value);        //"Foo" 
    alert(arguments[0]); //非嚴(yán)格模式:"Foo" 
                         //嚴(yán)格模式:"Hi"
}
showValue("Hi");

在函數(shù)內(nèi)部,value被改為"Foo"。在非嚴(yán)格模式下,這個修改也會改變arguments[0]的值,但在嚴(yán)格模式下,arguments[0]的值仍然是傳入的值。
另一個變化是淘汰了arguments.calleearguments.caller。在非嚴(yán)格模式下,這兩個屬性一個引用函數(shù)本身,一個引用調(diào)用函數(shù)。而在嚴(yán)格模式下,訪問哪個屬性都會拋出TypeError

//訪問 arguments.callee 
//非嚴(yán)格模式:沒有問題 
//嚴(yán)格模式:拋出 TypeError
function factorial(num){
    if (num <= 1) {
        return 1;
    } else {
        return num * arguments.callee(num-1)
    }
}
var result=factorial(5);

類似地,嘗試讀寫函數(shù)的caller屬性,也會導(dǎo)致拋出TypeError。所以,對于上面的例子而言, 訪問factorial.caller也會拋出錯誤。
與變量類似,嚴(yán)格模式對函數(shù)名也做出了限制,不允許用implements、interface、let、package、 private、protectedpublic、staticyield作為函數(shù)名。
對函數(shù)的最后一點限制,就是只能在腳本的頂級和在函數(shù)內(nèi)部聲明函數(shù)。也就是說,在if語句中聲明函數(shù)會導(dǎo)致語法錯誤:

//在 if 語句中聲明函數(shù) 
//非嚴(yán)格模式:將函數(shù)提升到 if 語句外部 
//嚴(yán)格模式:拋出語法錯誤
if (true){
    function doSomething(){ 
          //...
    }
}

eval()

eval()函數(shù)在嚴(yán)格模式下也得到了提升。最大的變化就是它在包含上下文中不再創(chuàng)建變量或函數(shù)。

//使用 eval()創(chuàng)建變量
//非嚴(yán)格模式:彈出對話框顯示 10
//嚴(yán)格模式:調(diào)用 alert(x)時會拋出 ReferenceError
function doSomething(){ 
    eval("var x=10"); 
    alert(x);
}

如果是在非嚴(yán)格模式下,以上代碼會在函數(shù)doSomething()中創(chuàng)建一個局部變量x,然后alert()還會顯示該變量的值。但在嚴(yán)格模式下,在doSomething()函數(shù)中調(diào)用eval()不會創(chuàng)建變量x,因此調(diào)用alert()會導(dǎo)致拋出ReferenceError,因為x沒有定義。
可以在eval()中聲明變量和函數(shù),但這些變量或函數(shù)只能在被求值的特殊作用域中有效,隨后就將被銷毀。

"use strict";
var result = eval("var x=10, y=11; x+y"); 
alert(result); //21

在調(diào)用alert()時,盡管xy已經(jīng)不存在了,result變量的值仍然是有效的。

eval與arguments

嚴(yán)格模式已經(jīng)明確禁止使用evalarguments作為標(biāo)識符,也不允許讀寫它們的值。

//把eval和arguments作為變量引用 
//非嚴(yán)格模式:沒問題,不出錯 
//嚴(yán)格模式:拋出語法錯誤
var eval = 10;
var arguments = "Hello world!";

在非嚴(yán)格模式下,可以重寫eval,也可以給arguments賦值。但在嚴(yán)格模式下,這樣做會導(dǎo)致語法錯誤。不能將它們用作標(biāo)識符,意味著以下幾種使用方式都會拋出語法錯誤:

  • 使用var聲明;
  • 賦予另一個值;
  • 嘗試修改包含的值,如使用++;
  • 用作函數(shù)名;
  • 用作命名的函數(shù)參數(shù);
  • try-catch語句中用作例外名。

抑制this

在非嚴(yán)格模式下使用函數(shù)的apply()call()方法時,nullundefined值會被轉(zhuǎn)換為全局對象。而在嚴(yán)格模式下,函數(shù)的this值始終是指定的值,無論指定的是什么值。

//訪問屬性
//非嚴(yán)格模式:訪問全局屬性 
//嚴(yán)格模式:拋出錯誤,因為this的值為null
var color = "red";
function displayColor(){ 
    alert(this.color);
}
displayColor.call(null);

其他變化

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

//with的語句用法 
//非嚴(yán)格模式:允許 
//嚴(yán)格模式:拋出語法錯誤
with(location){ 
    alert(href);
}

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

//使用八進制字面量 
//非嚴(yán)格模式:值為 8 
//嚴(yán)格模式:拋出語法錯誤
var value = 010;

八進制字面量在嚴(yán)格模式下會被當(dāng)作以0開頭的十進制字面量。

//使用parseInt()解析八進制字面量 
//非嚴(yán)格模式:值為 8 
//嚴(yán)格模式:值為 10
var value = parseInt("010");
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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