Javascript的版本較多,主要由于是在瀏覽器端運行的語言,加上微軟早起的策略影響,導致運行環境多種多樣,除開現代瀏覽器能夠不斷的更新支持新的標準,IE6大家族,幾乎可以說每一代都是不同的Javascript運行環境,這也就導致了許多兼容性的問題.因此,我們在編寫Javascript的時候,需要明確的知道我們所使用的是哪個版本的Javascript,版本不同,特性也不同,所能運行的環境也是大不相同.
Strict Mode
Strict 模式,使語言能夠按照ES5的要求進行需要排錯檢測,同時又能夠兼容在低版本的瀏覽器中運行.
Strict模式的定義非常簡單,只主要在文件或者函數體的開頭加上use strict
即可,這樣,在支持ES5的瀏覽器的環境上面運行這段代碼,瀏覽器就會按照ES5的標準來對JS進行語法排錯.
為什么能在老舊的瀏覽器中運行?
JS的語法是向后兼容的,因而按照ES5編寫的JS,是能夠準確無誤的在老舊瀏覽器中運行的,因而對于語法來說,是肯定沒有問題的,但是,多出來的use strict
又是否可以會有副作用呢?答案是否定的,我們可以理解為use strict
是定義了一個字符串的變量,但是因為沒有變量名,老舊的瀏覽器在給其分配了內存以后,又會馬上的回收,因而不會產生副作用.
Strict Mode的陷阱
Strict Mode固然好,但是一不留神,就坑踩到其中的坑.其中一個比較大的坑就是,use strict
語句只有在JS文件或者函數的頂部才能生效,如果僅僅只是編寫一個文件,當然沒有問題,但是,如果我們的JS文件是多個不同的人員編寫,然后統一組裝起來的呢?這個時候,就會帶來兼容性的問題了.
//file1.js
"use strict";
function f() {
// ...
}
// ...
// file2.js
// no strict-mode directive
function g() {
var arguments = [];
// ...
}
// ...
如果我們直接把這兩個文件拼湊起來,直接就會報錯,為什么呢?因為在file1.js
中,我們定義了use strict
模式,但是file2.js
是別人寫的,并沒有使用嚴格模式,所以直接連接在一起的時候,file2.js
也會因此而被ES5語法檢查,從而導致報錯.
那么,有沒有辦法可以解決這個問題呢?有人會想著,我把這兩個換過來不就行了唄.真的是這么簡單的?答案是否定的,前面我們說過,use strict
聲明只要在文件的開頭或者函數體的開頭才會生效,如果我們直接把文件進行替換,use strict
這個聲明既不是在文件的頂端,又不是在函數體的開頭,自然會導致失效.雖然這樣不會報錯,但是這就失去了嚴格模式的意義了,從而導致部分代碼的錯誤無法發現.
那么,對于這類由不同人員開發,并且是否使用嚴格模式不統一的情況下,我們要如何處理呢?
一個很直觀的方法就是,不要把使用了嚴格模式和沒使用嚴格模式的文件進行組合,把他們分別進行組合,HTML引入兩個文件,這是一個解決辦法,但是這只是一個妥協折中的辦法,并不是真的解決了這個問題.
還有另外一個辦法,可以比較完美的解決這個問題,就是IIFEs(immediately invoked function expressions)
.相信大家有JS基礎的話,都會對IIFEs
有所了解吧,在某些異步的場景中,我們可以通過IIFEs
來對每次的異步狀態進行保存.廢話誰說,直接看代碼
// no strict-mode directive
(function() {
// file1.js
"use strict";
function f() {
// ...
}
// ...
})();
(function() {
// file2.js
// no strict-mode directive
function f() {
var arguments = [];
// ...
}
// ...
})();
我們分別把不同的文件使用一個括號進行包圍起來,這樣,這兩個文件就分別處于不同的scope中的,use strict
模式只會影響在同一個括號里面的代碼,不會影響括號以外的代碼,因此也是實現了他們之間的和平共處.
在ES6沒有出來之前,大部分的模塊化也是借鑒這樣的方式實現的,這樣里面定義的函數和變量都不再是全局的,而是僅僅再括號內部能夠使用.
但是,如果我們在寫一個庫的時候,我們無法預想到以后的運行環境是怎么樣的,有可能我們的函數會被打包連接工具打包起來,就會打破了我們所定義了strict模式,因而,如果我們希望自己所編寫的代碼無論在什么時候都是在strict模式運行的話,就可以選擇在對每一個函數都使用括號進行包裹,然后調用IIFEs
機制.
(function() {
"use strict";
function f() {
// ...
}
// ...
})();
總結
- 決定你的應用使用哪一種Javascript版本
- 確定你使用的Javascript版本的所有特性都能夠被應用運行的環境所支持
- 總是使用支持strict模式的環境來測試strict模式的代碼
- 知道在鏈接不同的Javascript代碼的時候的不同點