js中l(wèi)et能否完全替代IIFE
前言
最近,我寫(xiě)了一篇關(guān)于syntax of Java's IIFE pattern的文章,來(lái)解釋為什么我們用現(xiàn)在的方式來(lái)寫(xiě)立即執(zhí)行函數(shù)表達(dá)式。少數(shù)的讀者批評(píng)文章過(guò)時(shí)了,都在爭(zhēng)論在ECMA 2015中介紹的塊級(jí)作用域變量使IIFE變得過(guò)時(shí)了。
恰恰相反,立即執(zhí)行函數(shù)表達(dá)式一點(diǎn)也沒(méi)有過(guò)時(shí)!因?yàn)檫@個(gè)理由,我決定寫(xiě)這篇后續(xù)文章來(lái)介紹一些立即執(zhí)行函數(shù)表達(dá)式的常見(jiàn)用法。注意以下的列表是不完整的,所以如果你喜歡的用法沒(méi)有在文章出現(xiàn),希望你不要有什么不好的感覺(jué)。
函數(shù)作用域 VS 塊級(jí)作用域
通過(guò)var關(guān)鍵字聲明的本地變量?jī)H作用于當(dāng)前閉包域,如果不存在這樣的一個(gè)閉包函數(shù),那么將會(huì)創(chuàng)建一個(gè)污染全局作用域的全局變量。為了防止這種情況出現(xiàn),我們可以使用IIFE來(lái)創(chuàng)建一個(gè)包含有這個(gè)本地變量的函數(shù)。
(function(){ varfoo= "bar"; console.log(foo); })(); foo;// ReferenceError: foo is not defined
目前的爭(zhēng)論是,我們可以使用在ECMA 2015介紹的塊級(jí)作用域變量來(lái)代替IIFE,以達(dá)到相同的效果。相比于函數(shù)級(jí)作用域,let和const關(guān)鍵字聲明的本地變量?jī)H作用于當(dāng)前所處的”塊”級(jí)域。
{ let foo= "bar"; console.log(foo); } foo;// ReferenceError: foo is not defined
然而,塊級(jí)作用域變量不是立即函數(shù)執(zhí)行表達(dá)式的替代品。確實(shí),如果支持ECMA 2015,let和const能夠用來(lái)限制本地變量只在包含它的塊級(jí)作用域內(nèi)使用。
如果,你在不支持ECMA 2015的環(huán)境(例如一些舊的瀏覽器)中執(zhí)行你的Java代碼。你就不能使用let和const關(guān)鍵字來(lái)創(chuàng)建塊級(jí)作用域變量。你將不得不求助于以前經(jīng)典的函數(shù)級(jí)作用域方法。
閉包和私有數(shù)據(jù)
IIFE的另一個(gè)用法是為局部變量提供一個(gè)封裝的作用域,在IIFE返回的函數(shù)中能夠訪(fǎng)問(wèn)該變量。這種方式即_a closure is created_允許函數(shù)訪(fǎng)問(wèn)這個(gè)本地變量,即使這個(gè)函數(shù)在IIFE的詞法范圍之外執(zhí)行時(shí)。
假設(shè)我們要?jiǎng)?chuàng)建一個(gè)uniqueId函數(shù),每次調(diào)用該函數(shù)時(shí)就會(huì)返回一個(gè)唯一的id(比如 “id_1”,“id_2”等)。在下面的IIFE中,記錄了一個(gè)私有的計(jì)數(shù)變量(count),每次調(diào)用計(jì)數(shù)函數(shù)uniqueId的時(shí)候,就會(huì)將count加一。我們?cè)贗IFE中返回的另一個(gè)函數(shù),這個(gè)函數(shù)在調(diào)用時(shí)會(huì)返回一個(gè)新的標(biāo)識(shí)符字符串。
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之外無(wú)法訪(fǎng)問(wèn)這個(gè)計(jì)數(shù)變量count。除了從IIEF中返回的函數(shù),別人無(wú)法讀寫(xiě)該變量。這樣就能創(chuàng)建真正的私有狀態(tài),它只能以受控的方式進(jìn)行修改。revealing module pattern非常依賴(lài)于這種機(jī)制。
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
當(dāng)使用IIFE來(lái)返回一個(gè)”封閉”一些本地變量來(lái)管理私有數(shù)據(jù)的函數(shù)時(shí),let和const都不能替代它。
變量重命名
有時(shí),你可能碰到一種情況,你正在使用的兩個(gè)不同的庫(kù)暴露的全局變量名是相同的。例如,考慮一下你正在使用jQuery同時(shí)另一個(gè)庫(kù)也指定了一個(gè)為$的全局變量。
為了解決命名沖突問(wèn)題,可以將一段代碼封裝在一個(gè)IIEF中,將一個(gè)全局變量(比如,jQuery)作為參數(shù)傳入IIFE。在函數(shù)內(nèi)部,就可以以一個(gè)任意的參數(shù)名(比如,$)來(lái)訪(fǎng)問(wèn)該參數(shù)值:
window.$= functionsomethingElse(){ // ... }; (function($){ // ... })(jQuery);
不管在外部作用域有什么值指定給$,在IIFE中,這些值都會(huì)被”屏蔽”,$參數(shù)一直指向jQuery方法。
捕獲全局對(duì)象
Java代碼在不同環(huán)境執(zhí)行時(shí),你所使用的全局對(duì)象是不同的。當(dāng)代碼在瀏覽器運(yùn)行時(shí),全局對(duì)象是windows。但是在Node.js中,全局對(duì)象是global。由于在寫(xiě)通用的Java代碼時(shí),你肯定不想硬編碼這兩個(gè)名字其中的任何一個(gè),這時(shí)你就可以使用一種”包裝”的方式就像下面這樣:
(function(global){ // ... })(this);
不管是瀏覽器還是Node.js的環(huán)境,global參數(shù)將會(huì)指定到對(duì)的全局對(duì)象上。如果想了解更多關(guān)于使用這種技巧來(lái)捕獲全局對(duì)象的細(xì)節(jié)內(nèi)容,請(qǐng)移步this post by Todd Motto。
壓縮方面的優(yōu)化
混疊變量名的方法也可以用來(lái)優(yōu)化代碼,這種方式使代碼能夠被更有效的壓縮。舉例如下:
(function(window,document,undefined){ // ... })(window,document);
更短標(biāo)識(shí)符名會(huì)使文件的體積變得更小。然而,如果HTTP的返回內(nèi)容通過(guò)Gzip或者Deflate進(jìn)行壓縮,文件的大小已經(jīng)被很有效的壓縮了。因此,如果結(jié)合壓縮算法,壓縮技術(shù)的邊際收益會(huì)變得更小。所以自己權(quán)衡和比較返回內(nèi)容的大小,較短的名字可能仍然是有作用的。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS實(shí)現(xiàn)鼠標(biāo)滑過(guò)鏈接改變網(wǎng)頁(yè)背景顏色的方法
這篇文章主要介紹了JS實(shí)現(xiàn)鼠標(biāo)滑過(guò)鏈接改變網(wǎng)頁(yè)背景顏色的方法,涉及js響應(yīng)鼠標(biāo)事件動(dòng)態(tài)修改頁(yè)面元素屬性的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10javascript:json數(shù)據(jù)的頁(yè)面綁定示例代碼
本篇文章主要是對(duì)javascript:json數(shù)據(jù)的頁(yè)面綁定示例代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01微信小程序?qū)崿F(xiàn)人臉識(shí)別登陸的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)人臉識(shí)別登陸的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04javascript學(xué)習(xí)筆記之函數(shù)定義
本文主要給大家介紹了javascript的一些函數(shù)定義方面的基礎(chǔ)知識(shí),包括函數(shù)聲明式、函數(shù)表達(dá)式、Function 構(gòu)造函數(shù)等,十分的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。2015-06-06javascript下利用數(shù)組緩存正則表達(dá)式的實(shí)現(xiàn)方法
利用組存大法要提高我們程序的性能,讓我們的正則表達(dá)式的創(chuàng)建于執(zhí)行更有效率。2009-12-12淺談es6中export和export default的作用及區(qū)別
下面小編就為大家分享一篇淺談es6中export和export default的作用及區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02JS中style.display和style.visibility的區(qū)別實(shí)例說(shuō)明
下面的例子說(shuō)明了這種區(qū)別:在這個(gè)例子中,divContent1和divContent2隱藏的時(shí)候用的是style.display=none,這時(shí)候,后面的div會(huì)向上移動(dòng),占據(jù)已經(jīng)隱藏的div的空間。divContent3和divContent4用的是style.visibility=hidden來(lái)隱藏,但是其隱藏后仍然占據(jù)原來(lái)的空間2013-03-03Javascript 模擬點(diǎn)擊事件(點(diǎn)擊鏈接與html點(diǎn)擊) 兼容IE/Firefox
Javascript 模擬點(diǎn)擊事件,一般情況下ie支持的,firefox并不支持。所以可以通過(guò)下面的方法解決。2010-01-01