JS嚴(yán)格模式

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

選擇使用

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

"use strict";

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

function doSomething(){ 
    "use strict";

    //其他代碼
}

變量

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

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

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

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

嚴(yán)格模式下對(duì)變量名也有限制。特別地,不能使用implementsinterface、letpackage、private、protected、public、staticyield作為變量名。這些都是保留字。在嚴(yán)格模式下,用以上標(biāo)識(shí)符作為變量名會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤。

對(duì)象

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

  • 為只讀屬性賦值會(huì)拋出TypeError;
  • 對(duì)不可配置的的屬性使用delete操作符會(huì)拋出TypeError
  • 為不可擴(kuò)展的的對(duì)象添加屬性會(huì)拋出TypeError。

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

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

函數(shù)

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

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

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

//修改命名參數(shù)的值 
//非嚴(yán)格模式:修改會(huì)反映到 arguments 中 
//嚴(yán)格模式:修改不會(huì)反映到 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)格模式下,這個(gè)修改也會(huì)改變arguments[0]的值,但在嚴(yán)格模式下,arguments[0]的值仍然是傳入的值。
另一個(gè)變化是淘汰了arguments.calleearguments.caller。在非嚴(yán)格模式下,這兩個(gè)屬性一個(gè)引用函數(shù)本身,一個(gè)引用調(diào)用函數(shù)。而在嚴(yán)格模式下,訪問哪個(gè)屬性都會(huì)拋出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屬性,也會(huì)導(dǎo)致拋出TypeError。所以,對(duì)于上面的例子而言, 訪問factorial.caller也會(huì)拋出錯(cuò)誤。
與變量類似,嚴(yán)格模式對(duì)函數(shù)名也做出了限制,不允許用implementsinterface、letpackage、 private、protected、publicstaticyield作為函數(shù)名。
對(duì)函數(shù)的最后一點(diǎn)限制,就是只能在腳本的頂級(jí)和在函數(shù)內(nèi)部聲明函數(shù)。也就是說(shuō),在if語(yǔ)句中聲明函數(shù)會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤:

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

eval()

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

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

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

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

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

eval與arguments

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

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

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

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

抑制this

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

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

其他變化

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

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

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

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

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

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

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

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