javascript嚴格模式

ECMAScript 5 最先引入了「嚴格模式」(strict mode)的概念。經過嚴格模式,能夠在函數內部編程

選擇進行較爲嚴格的全局或局部的錯誤條件檢測。使用嚴格模式的好處是能夠提前知道代碼中瀏覽器

存在的錯誤,及時捕獲一些可能致使編程錯誤的ECMAScript 行爲。安全

理解嚴格模式的規則很是重要,ECMAScript 的下一個版本將以嚴格模式爲基礎制定。支持嚴格模app

式的瀏覽器包括IE10+、Firefox 4+、Safari 5.1+和Chrome。函數

 

1.選擇使用測試

要選擇進入嚴格模式,可使用嚴格模式的編譯指示(pragma),實際上就是一個不會賦給任何變this

量的字符串:spa

"use strict";code

這種語法(從ECMAScript 3 開始支持)能夠向後兼容那些不支持嚴格模式的JavaScript 引擎。支持orm

嚴格模式的引擎會啓動這種模式,而不支持該模式的引擎就當遇到了一個未賦值的字符串字面量,會忽

略這個編譯指示。

若是是在全局做用域中(函數外部)給出這個編譯指示,則整個腳本都將使用嚴格模式。換句話說,

若是把帶有這個編譯指示的腳本放到其餘文件中,則該文件中的JavaScript 代碼也將處於嚴格模式下。

也能夠只在函數中打開嚴格模式,就像下面這樣:

function doSomething(){"use strict";//其餘代碼}

 

若是你沒有控制頁面中全部腳本的權力,建議只在須要測試的特定函數中開啓嚴格模式。

 

2 .變量

在嚴格模式下,何時建立變量以及怎麼建立變量都是有限制的。首先,不容許意外建立全局變

量。在非嚴格模式下,能夠像下面這樣建立全局變量:

 

//未聲明變量//非嚴格模式:建立全局變量//嚴格模式:拋出ReferenceErrormessage = "Hello world! ";

 

即便message 前面沒有var 關鍵字,即便沒有將它定義爲某個全局對象的屬性,也能將message

建立爲全局變量。但在嚴格模式下,若是給一個沒有聲明的變量賦值,那代碼在執行時就會拋出

ReferenceError。

其次,不能對變量調用delete 操做符。非嚴格模式容許這樣操做,但會靜默失敗(返回false)。

而在嚴格模式下,刪除變量也會致使錯誤。

 

//刪除變量//非嚴格模式:靜默失敗//嚴格模式:拋出ReferenceErrorvar color = "red";delete color;

 

嚴格模式下對變量名也有限制。特別地,不能使用implements、interface、let、package、

private、protected、public、static 和yield 做爲變量名。這些都是保留字,未來的ECMAScript

版本中可能會用到它們。在嚴格模式下,用以上標識符做爲變量名會致使語法錯誤。

 

3.對象

在嚴格模式下操做對象比在非嚴格模式下更容易致使錯誤。通常來講,非嚴格模式下會靜默失敗的
情形,在嚴格模式下就會拋出錯誤。所以,在開發中使用嚴格模式會加大早發現錯誤的可能性。
在下列情形下操做對象的屬性會致使錯誤:
 爲只讀屬性賦值會拋出TypeError;
 對不可配置的(nonconfigurable)的屬性使用delete 操做符會拋出TypeError;
 爲不可擴展的(nonextensible)的對象添加屬性會拋出TypeError。
使用對象的另外一個限制與經過對象字面量聲明對象有關。在使用對象字面量時,屬性名必須惟一。
例如:

複製代碼

//重名屬性//非嚴格模式:沒有錯誤,以第二個屬性爲準//嚴格模式:拋出語法錯誤var person = {
name: "Nicholas",
name: "Greg"};

複製代碼

這裏的對象person 有兩個屬性,都叫name。在非嚴格模式下,person 對象的name 屬性值是第
二個,而在嚴格模式下,這樣的代碼會致使語法錯誤。

 

4.函數

首先,嚴格模式要求命名函數的參數必須惟一。如下面這個函數爲例:

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

在非嚴格模式下,這個函數聲明不會拋出錯誤。經過參數名只能訪問第二個參數,要訪問第一個參

數必須經過arguments 對象。

在嚴格模式下,arguments 對象的行爲也有所不一樣。在非嚴格模式下,修改命名參數的值也會反

映到arguments 對象中,而嚴格模式下這兩個值是徹底獨立的。例如:

複製代碼

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

複製代碼

以上代碼中,函數showValue()只有一個命名參數value。調用這個函數時傳入了一個參數"Hi",

這個值賦給了value。而在函數內部,value 被改成"Foo"。在非嚴格模式下,這個修改也會改變

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

另外一個變化是淘汰了arguments.callee 和arguments.caller。在非嚴格模式下,這兩個屬

性一個引用函數自己,一個引用調用函數。而在嚴格模式下,訪問哪一個屬性都會拋出TypeError。

例如:

複製代碼

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

複製代碼

相似地,嘗試讀寫函數的caller 屬性,也會致使拋出TypeError。因此,對於上面的例子而言,

訪問factorial.caller 也會拋出錯誤。

與變量相似,嚴格模式對函數名也作出了限制,不容許用implements、interface、let、package、

private、protected、public、static 和yield 做爲函數名。

對函數的最後一點限制,就是隻能在腳本的頂級和在函數內部聲明函數。也就是說,在if 語句中

聲明函數會致使語法錯誤:

複製代碼

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

複製代碼

在非嚴格模式下,以上代碼能在全部瀏覽器中運行,但在嚴格模式下會致使語法錯誤。

 

5.eval()

飽受詬病的eval()函數在嚴格模式下也獲得了提高。最大的變化就是它在包含上下文中再也不建立

變量或函數。例如:

複製代碼

//使用eval()建立變量//非嚴格模式:彈出對話框顯示10//嚴格模式:調用alert(x)時會拋出ReferenceErrorfunction doSomething(){
eval("var x=10");
alert(x);
}

複製代碼

若是是在非嚴格模式下,以上代碼會在函數doSomething()中建立一個局部變量x,而後alert()

還會顯示該變量的值。但在嚴格模式下,在doSomething()函數中調用eval()不會建立變量x,所以

調用alert()會致使拋出ReferenceError,由於x 沒有定義。

能夠在eval()中聲明變量和函數,但這些變量或函數只能在被求值的特殊做用域中有效,隨後就

將被銷燬。所以,如下代碼能夠運行,沒有問題:

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

這裏在eval()中聲明瞭變量x 和y,而後將它們加在一塊兒,返回了它們的和。因而,result 變

量的值是21,即x 和y 相加的結果。而在調用alert()時,儘管x 和y 已經不存在了,result 變量

的值仍然是有效的。

 

6.eval與arguments

嚴格模式已經明確禁止使用eval 和arguments 做爲標識符,也不容許讀寫它們的值。例如:

//把eval 和arguments 做爲變量引用//非嚴格模式:沒問題,不出錯//嚴格模式:拋出語法錯誤var eval = 10;var arguments = "Hello world!";

在非嚴格模式下,能夠重寫eval,也能夠給arguments 賦值。但在嚴格模式下,這樣作會致使語

法錯誤。不能將它們用做標識符,意味着如下幾種使用方式都會拋出語法錯誤:

 使用var 聲明;

 賦予另外一個值;

 嘗試修改包含的值,如使用++;

 用做函數名;

 用做命名的函數參數;

 在try-catch 語句中用做例外名。

 

7.抑制this

JavaScript 中一個最大的安全問題,也是最容易讓人迷茫的地方,就是在某些狀況下如何抑制this

的值。在非嚴格模式下使用函數的apply()或call()方法時,null 或undefined 值會被轉換爲全局

對象。而在嚴格模式下,函數的this 值始終是指定的值,不管指定的是什麼值。例如:

複製代碼

//訪問屬性//非嚴格模式:訪問全局屬性//嚴格模式:拋出錯誤,由於this 的值爲nullvar color = "red";function displayColor(){
alert(this.color);
}
displayColor.call(null);

複製代碼

以上代碼向displayColor.call()中傳入了null,若是在是非嚴格模式下,這意味着函數的this

值是全局對象。結果就是彈出對話框顯示"red"。而在嚴格模式下,這個函數的this 的值是null,因

此在訪問null 的屬性時就會拋出錯誤。

 

8.其餘變化

嚴格模式還有其餘一些變化,但願讀者也能留意。首先是拋棄了with 語句。非嚴格模式下的with

語句可以改變解析標識符的路徑,但在嚴格模式下,with 被簡化掉了。所以,在嚴格模式下使用with

會致使語法錯誤。

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

嚴格模式也去掉了JavaScript 中的八進制字面量。以0 開頭的八進制字面量過去常常會致使不少錯

誤。在嚴格模式下,八進制字面量已經成爲無效的語法了。

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

ECMAScript 5 也修改了嚴格模式下parseInt()的行爲。現在,八進制字面量在

嚴格模式下會被看成以0 開頭的十進制字面量。例如:

//使用parseInt()解析八進制字面量//非嚴格模式:值爲8//嚴格模式:值爲10var value = parseInt("010");
相關文章
相關標籤/搜索