談談 JS 中的嚴格模式

什麼是嚴格模式?

嚴格模式 是 ECMAScript 5 中引入的一種將更好的錯誤檢查引入代碼中的方法, 如今已經被大多瀏覽器實現. 顧名思義,這種模式使得Javascript在更嚴格的條件下運行.chrome

所以, 在嚴格模式下, 咱們的一些不嚴謹的寫法將會致使程序拋出錯誤. 例如:瀏覽器

function fn(param) {
    var arguments = []; // 在嚴格模式下該行將會拋出錯誤: error: redefinition of arguments
}

在上面的代碼中, 因爲 arguments 在 js 中是一個特殊對象, 在嚴格模式下是不容許被從新定義的. 可是沒有實現嚴格模式檢查的環境中會接受這段代碼.安全

爲何會出現嚴格模式?

總所周知, 從 ECMAscript 從1997年正式成爲國際標準以來, 已經發布了6個版本. 除此以外, 還存在一些 Javascript 實現支持非標準特性, 而其餘的 Javascript 實現卻並不支持這些特性的狀況. 因爲 Javascript 的實現多樣化, 咱們很難肯定哪些特性在哪些平臺上是支持的, 再加上 Web 瀏覽器的複雜性, 而且它並不能讓開發者指定某一個特定的 Javascript 版原本執行咱們的程序. 所以咱們須要精心的編寫程序, 以確保在全部的平臺上都可以正常運行.性能優化

所以在 ES5 中引入了一種版本控制的考量: 嚴格模式. 此特性容許開發者選擇在受限制的 Javascript 版本中禁止使用一些 Javascript 語言中問題較多或是易於出錯的特性.函數

因爲其語法強大的向後兼容特性, 因此即便在沒有實現嚴格模式檢查的環境中, 你的嚴格代碼仍然能夠正常執行.工具

如何使用嚴格模式?

在程序中使用嚴格模式的方式是在程序中的最開始增長一個特定的字符串字面量.性能

"use strict"

若是你在一個文件的頂部加入這個特定的字符串, 則表示該文件的全部內容將始終使用嚴格模式執行.測試

若是你只想在一個函數體內使用嚴格模式, 則在該函數體內的最開始處(頂部)加入這句指令.優化

爲何要使用字符串字面量來實現嚴格模式?

單獨使用一個特定的字符串字面量來做爲指令語法在語言裏看起來確實至關怪異, 可是他有一個最大的好處是向後兼容. 咱們來看一下它爲何可以向後兼容. 咱們都知道在js 中解釋執行一個字符串字面量是沒有任何反作用的, 這句話什麼意思呢? 好比說你在 chrome 瀏覽器控制檯裏面輸入一個字符串字面量, 解釋器只會返回一個一樣的字符串, 除此以外不會發生任何事情, 這就使得即便ES3引擎不支持嚴格模式, 但依然可以無傷大雅的解釋和執行這條指令. ES3 引擎在解析完改字符串以後, 會當即將該值丟棄. 所以, 儘管舊的引擎不支持嚴格模式, 但依然可以正常運行.版本控制

但須要注意的是: 儘管不會拋出錯誤, 可是舊的引擎不會進行任何的嚴格檢查模式, 所以若是要使用嚴格模式, 你應該老是在徹底兼容ES5的環境中測試嚴格代碼.

使用嚴格模式須要注意哪些問題?

咱們在上面已經說過, use strict 指令須要寫在腳本或者函數的頂部, 由於該指令只有在寫在頂部才能生效. 這就使得咱們在使用的時候須要注意一下這裏有個小坑. 這個坑是什麼呢?

舉個例子, 咱們在開發大型功能的時候, 開發過程當中會使用多個獨立的腳本文件, 可是在部署到生產環境的時候出於性能優化的目的, 須要將多個腳本鏈接成一個單一的文件. 好比說, 腳本1 運行於嚴格模式下,

// file1.js 
"use strict"
function doSth() {
}

可是有另一個同事寫了一個腳本2運行於非嚴格模式下:

// file2.js
function doOtherSth(param) {
    var arguments = [];
}

那麼, 咱們該怎麼鏈接這兩個文件呢? 若是咱們以 file1.js 開始, 那麼鏈接後的代碼將運行於嚴格模式下, 可是因爲 file2 中的一些操做會在嚴格模式下拋出錯誤, 致使咱們的程序沒法正常運行.若是咱們以 file2.js 開始, 那麼鏈接後的代碼將運行於非嚴格模式下, 由於咱們前面已經講過該指令只有在寫在頂部才能生效. 彷佛怎樣都不太合適.

那麼如何解決這個問題呢?

  1. 在項目中堅持只使用嚴格模式或者只使用非嚴格模式, 而且不要將使用嚴格模式和不使用嚴格模式的文件進行打包構建. O(∩_∩)O哈哈~這樣就不會有問題了嘛.

  2. 咱們上面說過, 若是你只想在一個函數體內使用嚴格模式, 則在該函數體內的最開始處(頂部)加入這句指令. 咱們能夠利用這個特性, 將每個腳本文件裏面的代碼包裹在一個當即執行的函數表達式內, 這樣即便兩種模式的文件打包在一塊兒, 依然可以按照咱們的指望進行工做. 例如:

;(function() {
    // file1.js 
    "use strict"
    function doSth() {
    }
})();

;(function() {
    // file2.js 
    function doOtherSth() {
    }
})();

固然了, 上面這樣的作法會致使這些文件的內容不會在全局做用域內解釋, 這就致使咱們經過 varfunction 聲明的變量不會視爲全局變量. 不過這恰好對咱們來講也是一個很好的特性. 所以就放心大膽的使用吧, 去吧, 皮卡丘.

最佳實踐

上面的方法2看起來是極好的, 而且咱們能夠經過自動化構建工具爲咱們的腳本文件上添加如上代碼. 可是若是咱們想要編寫一個通用的庫, 使其能夠在儘量多的環境中正常工做, 咱們不能假設腳本文件必定會被構建工具置於一個當即執行的函數中, 也不能假設客戶端代碼必定處於嚴格模式或是非嚴格模式中. 因此爲了得到最佳效果, 咱們應該老是在嚴格模式下編寫代碼, 並顯式的將其包裹在啓用了嚴格模式的當即執行函數中, 而不是依靠構建工具來實現.

結語

"嚴格模式"體現了Javascript更合理、更安全、更嚴謹的發展方向. 爲了達到更爲廣泛的兼容性, 咱們應該老是在嚴格模式下編寫代碼.

相關文章
相關標籤/搜索