在JavaScript中使用嚴(yán)格模式(Strict Mode)
前言
ECMAScript5中引入的嚴(yán)格模式,通過讓JavaScript運(yùn)行環(huán)境對(duì)一些開發(fā)過程中最常見和不易發(fā)現(xiàn)的錯(cuò)誤做出和當(dāng)前不同的處理,來讓開發(fā)者擁有一個(gè)”更好”的JavaScript語言。很長一段時(shí)間內(nèi),由于只有Firefox支持嚴(yán)格模式,我曾對(duì)嚴(yán)格模式表示懷疑。但到了今天,所有主流的瀏覽器都在他們的最新版本中支持了嚴(yán)格模式(包括IE10,Opera12和Android4,IOS5)是時(shí)候開始使用嚴(yán)格模式了。
嚴(yán)格模式能起到什么作用?
嚴(yán)格模式為JavaScript引入了很多變化,我把他們分為兩類(明顯的和細(xì)微的)。細(xì)微改進(jìn)的目標(biāo)是修復(fù)當(dāng)前JavaScript中的一些細(xì)節(jié)問題,對(duì)于這些問題我不在這里進(jìn)行深入介紹;我在這里主要介紹嚴(yán)格模式引入的明顯變化,那些在你使用嚴(yán)格模式前應(yīng)該知道的概念和那些對(duì)你幫助最大的改變。
在開始學(xué)習(xí)具體特性前,請記住嚴(yán)格模式的一大目標(biāo)是讓你能更快更方便的調(diào)試。運(yùn)行環(huán)境在發(fā)現(xiàn)問題時(shí)顯性的拋出錯(cuò)誤比默不做聲的失敗或怪異行事(未開啟嚴(yán)格模式的JavaScript運(yùn)行環(huán)境經(jīng)常這樣)要好。嚴(yán)格模式會(huì)拋出更多錯(cuò)誤,但這是好事,因?yàn)檫@些錯(cuò)誤會(huì)喚起你注意并修復(fù)很多以前很難被發(fā)現(xiàn)的潛在問題。
1. 去除with關(guān)鍵詞
首先,嚴(yán)格模式中去除了with語句,包含with語句的代碼在嚴(yán)格模式中會(huì)拋出異常。所以使用嚴(yán)格模式的第一步:確保你的代碼中沒有使用with。
// 在嚴(yán)格模式中以下JavaScript代碼會(huì)拋出錯(cuò)誤 with (location) { alert(href); }
2. 防止意外為全局變量賦值
其次,局部變量在賦值前必須先進(jìn)行申明。在啟用嚴(yán)格模式之前,為一個(gè)未申明的局部變量復(fù)制時(shí)會(huì)自動(dòng)創(chuàng)建一個(gè)同名全局變量。這是Javacript程序中最容易出現(xiàn)的錯(cuò)誤之一, 在嚴(yán)格模式中嘗試這么做時(shí)會(huì)有顯性的異常拋出。
// 嚴(yán)格模式下會(huì)拋出異常 (function() { someUndeclaredVar = "foo"; }());
3. 函數(shù)中的this不再默認(rèn)指向全局
嚴(yán)格模式中另一個(gè)重要的變化是函數(shù)中未被定義或?yàn)榭? null or undefined)的this不在默認(rèn)指向全局環(huán)境(global)。這會(huì)造成一些依賴函數(shù)中默認(rèn)this行為的代碼執(zhí)行出錯(cuò),例如:
window.color = "red"; function sayColor() { alert(this.color); } // 在strict模式中會(huì)報(bào)錯(cuò), 如果不在嚴(yán)格模式中則提示 “red" sayColor(); // 在strict模式中會(huì)報(bào)錯(cuò), 如果不在嚴(yán)格模式中則提示 “red" sayColor.call(null);
this在被賦值之前會(huì)一直保持為undefined,這意味著當(dāng)一個(gè)構(gòu)造函數(shù)在執(zhí)行時(shí),如果之前沒有明確的new關(guān)鍵詞,會(huì)拋出異常。
function Person(name) { this.name = name; } //在嚴(yán)格模式中會(huì)報(bào)錯(cuò) var me = Person("Nicholas");
在上面的代碼中,Person構(gòu)造函數(shù)運(yùn)行時(shí)因?yàn)橹皼]有new,函數(shù)中的this會(huì)保留為undefined, 由于你不能為undefined設(shè)置屬性,上面的代碼會(huì)拋出錯(cuò)誤。 在非strict模式環(huán)境中,沒有被復(fù)制的this會(huì)默認(rèn)指向window全局變量,運(yùn)行的結(jié)果將是意外的為window全局變量設(shè)置name屬性。
4. 防止重名
當(dāng)編寫大量代碼時(shí),對(duì)象屬性和函數(shù)參數(shù)很容易一不小心被設(shè)置成一個(gè)重復(fù)的名字。嚴(yán)格模式在這種情況下會(huì)顯性的拋出錯(cuò)誤
//重復(fù)的變量名,在嚴(yán)格模式下會(huì)報(bào)錯(cuò) function doSomething(value1, value2, value1) { //code } //重復(fù)的對(duì)象屬性名,在嚴(yán)格模式下會(huì)報(bào)錯(cuò): var object = { foo: "bar", foo: "baz" };
以上的代碼在嚴(yán)格模式中都會(huì)被認(rèn)為是語法錯(cuò)誤而在執(zhí)行前就讓你能得到提示。
5. 安全的 eval()
雖然eval()語句最終沒有被移除,但在嚴(yán)格模式中仍然對(duì)它進(jìn)行了一些改進(jìn)。最大的改變是在eval()中執(zhí)行的變量和函數(shù)申明不會(huì)直接在當(dāng)前作用域中創(chuàng)建相應(yīng)變量或函數(shù),例如:
(function() { eval("var x = 10;"); // 非嚴(yán)格模式中,alert 10 // 嚴(yán)格模式中則因x未被定義而拋出異常, alert(x); }());
任何在eval()執(zhí)行過程中創(chuàng)建的變量或者函數(shù)保留在eval()中。但你能明確的從eval()語句的返回值來獲取eval()中的執(zhí)行結(jié)果,例如:
(function() { var result = eval("var x = 10, y = 20; x + y"); // 在strict或非strict模式中都能正確的運(yùn)行余下的語句.(resulst為30) alert(result); }());
6. 對(duì)只讀屬性修改時(shí)拋出異常
ECMAScript5中還引入為對(duì)象的特定屬性設(shè)為只讀,或讓整個(gè)對(duì)象不可修改的能力。 但在非嚴(yán)格模式中,嘗試修改一個(gè)只讀屬性只會(huì)默不做聲的失敗。 在你和一些瀏覽器原生API打交道過程中,你很可能遇到這種情況。嚴(yán)格模式會(huì)在這種情況下明確的拋出異常,提醒你修改這個(gè)屬性是不被允許的。
var person = {}; Object.defineProperty(person, "name" { writable: false, value: "Nicholas" }); // 在非嚴(yán)格模式時(shí),沉默的失敗,在嚴(yán)格模式則拋出異常.
person.name = "John"; 上面的例子中,name屬性被設(shè)為只讀,非嚴(yán)格模式中執(zhí)行對(duì)name屬性的修改不會(huì)引發(fā)報(bào)錯(cuò),但修改不會(huì)成功。但嚴(yán)格模式則會(huì)明確的拋出異常。
NOTE: 強(qiáng)烈建議你在使用任何ECMAScript屬性特性指定時(shí)開啟嚴(yán)格模式。
如何使用?
在現(xiàn)代瀏覽器中開啟嚴(yán)格模式非常容易,只需要在JavaScript代碼中出現(xiàn)以下指令即可:
"use strict";
雖然看上去上面的代碼僅僅只是未賦予某個(gè)變量的字符串,它實(shí)際上起到指示JavaScript引擎切換到嚴(yán)格模式的作用(不支持嚴(yán)格模式的瀏覽器會(huì)忽略以上代碼,不會(huì)對(duì)后續(xù)的執(zhí)行產(chǎn)生任何影響)。雖然你能把這個(gè)指令作用到全局或某個(gè)函數(shù)中,但這里還是要提醒,不要在全局環(huán)境下啟用嚴(yán)格模式。
// 請不要這么使用 "use strict"; function doSomething() { // 這部分代碼會(huì)運(yùn)行于嚴(yán)格模式 } function doSomethingElse() { // 這部分代碼也會(huì)運(yùn)行于嚴(yán)格模式 }
雖然上面的代碼看起來不算一個(gè)大問題。但當(dāng)你不負(fù)責(zé)維護(hù)頁面中引入的全部代碼時(shí),這樣使用strict模式會(huì)讓你面臨由于第三方代碼沒有為嚴(yán)格模式做好準(zhǔn)備而引發(fā)的問題。 因此,最好把開啟嚴(yán)格模式的指令作用于函數(shù)中,例如:
function doSomething() { "use strict"; // 這個(gè)函數(shù)中的代碼將會(huì)運(yùn)行于嚴(yán)格模式 } function doSomethingElse() { // 這個(gè)函數(shù)中代碼不會(huì)運(yùn)行于嚴(yán)格模式 }
如果你想讓嚴(yán)格模式在不止一個(gè)函數(shù)中開啟,請使用立即執(zhí)行函數(shù)表達(dá)式
(immediately-invoked function expression ,IIFE): (function() { "use strict"; function doSomething() { // 這個(gè)函數(shù)運(yùn)行于嚴(yán)格模式 } function doSomethingElse() { // 這個(gè)函數(shù)同樣運(yùn)行于嚴(yán)格模式 } }());
結(jié)論
我強(qiáng)烈建議你從現(xiàn)在開始就啟用JavaScript嚴(yán)格模式,它能幫你發(fā)現(xiàn)代碼中未曾注意到的錯(cuò)誤。不要在全局環(huán)境中啟用,但你能盡量多的使用IIFE(立即執(zhí)行函數(shù)表達(dá)式)來把嚴(yán)格模式作用到多個(gè)函數(shù)范圍內(nèi)。
一開始,你會(huì)遇到之前未曾碰到過的錯(cuò)誤提示,這是正常的。當(dāng)啟用嚴(yán)格模式后,請確保在支持的瀏覽器中做了測試,以發(fā)現(xiàn)新的潛在問題。
一定不要僅僅在代碼中添加一行”use strict”就假定余下的代碼能正常工作。最后,請?jiān)趪?yán)格模式下開始編寫更好的代碼。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- JavaScript 引用類型實(shí)例詳解【數(shù)組、對(duì)象、嚴(yán)格模式等】
- JS嚴(yán)格模式原理與用法實(shí)例分析
- JavaScript 嚴(yán)格模式(use strict)用法實(shí)例分析
- javascript嚴(yán)格模式詳解(含嚴(yán)格模式與非嚴(yán)格模式的區(qū)別)
- JavaScript變量提升和嚴(yán)格模式實(shí)例分析
- 深入淺析JS中的嚴(yán)格模式
- JS嚴(yán)格模式知識(shí)點(diǎn)總結(jié)
- JavaScript嚴(yán)格模式下關(guān)于this的幾種指向詳解
- 深入理解javascript嚴(yán)格模式(Strict Mode)
- JavaScript嚴(yán)格模式不支持八進(jìn)制的問題講解
相關(guān)文章
js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明
本篇文章主要介紹了js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-12-12JS根據(jù)key值獲取URL中的參數(shù)值及把URL的參數(shù)轉(zhuǎn)換成json對(duì)象
本篇文章主要圍繞js url 參數(shù)值展開話題,js根據(jù)key值獲取url中的參數(shù)值,接著把url的參數(shù)轉(zhuǎn)換成json,感興趣的朋友一起來學(xué)習(xí)吧,本文寫的不好地方還望多多指出批評(píng)建議2015-08-08通過Javascript創(chuàng)建一個(gè)選擇文件的對(duì)話框代碼
通過Javascript創(chuàng)建一個(gè)選擇文件的對(duì)話框代碼,需要的朋友可以參考下2012-06-06JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表定義與使用方法示例
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)之雙向鏈表定義與使用方法,簡單介紹了雙向鏈表的原理,并結(jié)合實(shí)例形式分析了雙向鏈表的定義與使用方法,需要的朋友可以參考下2017-10-10js實(shí)現(xiàn)適用于素材網(wǎng)站的黑色多級(jí)菜單導(dǎo)航條效果
這篇文章主要介紹了js實(shí)現(xiàn)適用于素材網(wǎng)站的黑色多級(jí)菜單導(dǎo)航條效果,涉及javascript鼠標(biāo)事件及頁面元素樣式的動(dòng)態(tài)切換技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08