let可否徹底替代IIFE

let是什麼 http://es6.ruanyifeng.com/#docs/letes6

最近,我寫了一篇關於syntax of Java’s IIFE pattern的文章,來解釋爲何咱們用如今的方式來寫當即執行函數表達式。少數的讀者批評文章過期了,都在爭論在ECMA 2015中介紹的塊級做用域變量使IIFE變得過期了。算法

偏偏相反,當即執行函數表達式一點也沒有過期!由於這個理由,我決定寫這篇後續文章來介紹一些當即執行函數表達式的常見用法。注意如下的列表是不完整的,因此若是你喜歡的用法沒有在文章出現,但願你不要有什麼很差的感受。windows

函數做用域 VS 塊級做用域瀏覽器

經過var關鍵字聲明的本地變量僅做用於當前閉包域,若是不存在這樣的一個閉包函數,那麼將會建立一個污染全局做用域的全局變量。爲了防止這種狀況出現,咱們可使用IIFE來建立一個包含有這個本地變量的函數。閉包

(function(){函數

varfoo= "bar";工具

console.log(foo);post

})();優化

foo;// ReferenceError: foo is not definedthis

目前的爭論是,咱們可使用在ECMA 2015介紹的塊級做用域變量來代替IIFE,以達到相同的效果。相比於函數級做用域,let和const關鍵字聲明的本地變量僅做用於當前所處的」塊」級域。

{

let foo= "bar";

console.log(foo);

}

foo;// ReferenceError: foo is not defined

然而,塊級做用域變量不是當即函數執行表達式的替代品。確實,若是支持ECMA 2015,let和const可以用來限制本地變量只在包含它的塊級做用域內使用。

若是,你在不支持ECMA 2015的環境(例如一些舊的瀏覽器)中執行你的Java代碼。你就不能使用let和const關鍵字來建立塊級做用域變量。你將不得不求助於之前經典的函數級做用域方法。

閉包和私有數據

IIFE的另外一個用法是爲局部變量提供一個封裝的做用域,在IIFE返回的函數中可以訪問該變量。這種方式即_a closure is created_容許函數訪問這個本地變量,即便這個函數在IIFE的詞法範圍以外執行時。

假設咱們要建立一個uniqueId函數,每次調用該函數時就會返回一個惟一的id(好比 「id_1」,「id_2」等)。在下面的IIFE中,記錄了一個私有的計數變量(count),每次調用計數函數uniqueId的時候,就會將count加一。咱們在IIFE中返回的另外一個函數,這個函數在調用時會返回一個新的標識符字符串。

constuniqueId= (function(){

let count= 0;

returnfunction(){

++count;

returnid_${count};

};

})();

console.log(uniqueId());// "id_1"

console.log(uniqueId());// "id_2"

console.log(uniqueId());// "id_3"

注意,在IIEF以外沒法訪問這個計數變量count。除了從IIEF中返回的函數,別人沒法讀寫該變量。這樣就能建立真正的私有狀態,它只能以受控的方式進行修改。revealing module pattern很是依賴於這種機制。

constcounter= (function(){

let counterValue= 0;

return{

increment(){

++counterValue;

},

get value(){

returncounterValue;

}

};

})();

counter.increment();

console.log(counter.value);// 1

counter.increment();

counter.increment();

console.log(counter.value);// 3

當使用IIFE來返回一個」封閉」一些本地變量來管理私有數據的函數時,let和const都不能替代它。

變量重命名

有時,你可能碰到一種狀況,你正在使用的兩個不一樣的庫暴露的全局變量名是相同的。例如,考慮一下你正在使用jQuery同時另外一個庫也指定了一個爲$的全局變量。

爲了解決命名衝突問題,能夠將一段代碼封裝在一個IIEF中,將一個全局變量(好比,jQuery)做爲參數傳入IIFE。在函數內部,就能夠以一個任意的參數名(好比,$)來訪問該參數值:

window.$= functionsomethingElse(){

// ...

};

(function($){

// ...

})(jQuery);

無論在外部做用域有什麼值指定給$,在IIFE中,這些值都會被」屏蔽」,$參數一直指向jQuery方法。

捕獲全局對象

Java代碼在不一樣環境執行時,你所使用的全局對象是不一樣的。當代碼在瀏覽器運行時,全局對象是windows。可是在Node.js中,全局對象是global。因爲在寫通用的Java代碼時,你確定不想硬編碼這兩個名字其中的任何一個,這時你就可使用一種」包裝」的方式就像下面這樣:

(function(global){

// ...

})(this);

不論是瀏覽器仍是Node.js的環境,global參數將會指定到對的全局對象上。若是想了解更多關於使用這種技巧來捕獲全局對象的細節內容,請移步this post by Todd Motto。

壓縮方面的優化

混疊變量名的方法也能夠用來優化代碼,這種方式使代碼可以被更有效的壓縮。舉例以下:

(function(window,document,undefined){

// ...

})(window,document);

一個Java壓縮工具例如UglifyJS能夠縮短函數的參數名爲單個字母的標識符

(function(w,d,u){

// ...

})(window,document);

更短標識符名會使文件的體積變得更小。然而,若是HTTP的返回內容經過Gzip或者Deflate進行壓縮,文件的大小已經被頗有效的壓縮了。所以,若是結合壓縮算法,壓縮技術的邊際收益會變得更小。因此本身權衡和比較返回內容的大小,較短的名字可能仍然是有做用的。

相關文章
相關標籤/搜索