js中l(wèi)et能否完全替代IIFE
前言
最近,我寫了一篇關(guān)于syntax of Java's IIFE pattern的文章,來解釋為什么我們用現(xiàn)在的方式來寫立即執(zhí)行函數(shù)表達式。少數(shù)的讀者批評文章過時了,都在爭論在ECMA 2015中介紹的塊級作用域變量使IIFE變得過時了。
恰恰相反,立即執(zhí)行函數(shù)表達式一點也沒有過時!因為這個理由,我決定寫這篇后續(xù)文章來介紹一些立即執(zhí)行函數(shù)表達式的常見用法。注意以下的列表是不完整的,所以如果你喜歡的用法沒有在文章出現(xiàn),希望你不要有什么不好的感覺。
函數(shù)作用域 VS 塊級作用域
通過var關(guān)鍵字聲明的本地變量僅作用于當前閉包域,如果不存在這樣的一個閉包函數(shù),那么將會創(chuàng)建一個污染全局作用域的全局變量。為了防止這種情況出現(xiàn),我們可以使用IIFE來創(chuàng)建一個包含有這個本地變量的函數(shù)。
(function(){
varfoo= "bar";
console.log(foo);
})();
foo;// ReferenceError: foo is not defined
目前的爭論是,我們可以使用在ECMA 2015介紹的塊級作用域變量來代替IIFE,以達到相同的效果。相比于函數(shù)級作用域,let和const關(guān)鍵字聲明的本地變量僅作用于當前所處的”塊”級域。
{
let foo= "bar";
console.log(foo);
}
foo;// ReferenceError: foo is not defined
然而,塊級作用域變量不是立即函數(shù)執(zhí)行表達式的替代品。確實,如果支持ECMA 2015,let和const能夠用來限制本地變量只在包含它的塊級作用域內(nèi)使用。
如果,你在不支持ECMA 2015的環(huán)境(例如一些舊的瀏覽器)中執(zhí)行你的Java代碼。你就不能使用let和const關(guān)鍵字來創(chuàng)建塊級作用域變量。你將不得不求助于以前經(jīng)典的函數(shù)級作用域方法。
閉包和私有數(shù)據(jù)
IIFE的另一個用法是為局部變量提供一個封裝的作用域,在IIFE返回的函數(shù)中能夠訪問該變量。這種方式即_a closure is created_允許函數(shù)訪問這個本地變量,即使這個函數(shù)在IIFE的詞法范圍之外執(zhí)行時。
假設我們要創(chuàng)建一個uniqueId函數(shù),每次調(diào)用該函數(shù)時就會返回一個唯一的id(比如 “id_1”,“id_2”等)。在下面的IIFE中,記錄了一個私有的計數(shù)變量(count),每次調(diào)用計數(shù)函數(shù)uniqueId的時候,就會將count加一。我們在IIFE中返回的另一個函數(shù),這個函數(shù)在調(diào)用時會返回一個新的標識符字符串。
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之外無法訪問這個計數(shù)變量count。除了從IIEF中返回的函數(shù),別人無法讀寫該變量。這樣就能創(chuàng)建真正的私有狀態(tài),它只能以受控的方式進行修改。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來返回一個”封閉”一些本地變量來管理私有數(shù)據(jù)的函數(shù)時,let和const都不能替代它。
變量重命名
有時,你可能碰到一種情況,你正在使用的兩個不同的庫暴露的全局變量名是相同的。例如,考慮一下你正在使用jQuery同時另一個庫也指定了一個為$的全局變量。
為了解決命名沖突問題,可以將一段代碼封裝在一個IIEF中,將一個全局變量(比如,jQuery)作為參數(shù)傳入IIFE。在函數(shù)內(nèi)部,就可以以一個任意的參數(shù)名(比如,$)來訪問該參數(shù)值:
window.$= functionsomethingElse(){
// ...
};
(function($){
// ...
})(jQuery);
不管在外部作用域有什么值指定給$,在IIFE中,這些值都會被”屏蔽”,$參數(shù)一直指向jQuery方法。
捕獲全局對象
Java代碼在不同環(huán)境執(zhí)行時,你所使用的全局對象是不同的。當代碼在瀏覽器運行時,全局對象是windows。但是在Node.js中,全局對象是global。由于在寫通用的Java代碼時,你肯定不想硬編碼這兩個名字其中的任何一個,這時你就可以使用一種”包裝”的方式就像下面這樣:
(function(global){
// ...
})(this);
不管是瀏覽器還是Node.js的環(huán)境,global參數(shù)將會指定到對的全局對象上。如果想了解更多關(guān)于使用這種技巧來捕獲全局對象的細節(jié)內(nèi)容,請移步this post by Todd Motto。
壓縮方面的優(yōu)化
混疊變量名的方法也可以用來優(yōu)化代碼,這種方式使代碼能夠被更有效的壓縮。舉例如下:
(function(window,document,undefined){
// ...
})(window,document);
更短標識符名會使文件的體積變得更小。然而,如果HTTP的返回內(nèi)容通過Gzip或者Deflate進行壓縮,文件的大小已經(jīng)被很有效的壓縮了。因此,如果結(jié)合壓縮算法,壓縮技術(shù)的邊際收益會變得更小。所以自己權(quán)衡和比較返回內(nèi)容的大小,較短的名字可能仍然是有作用的。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
微信小程序?qū)崿F(xiàn)pdf、word等格式文件上傳的方法
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)pdf,word等格式文件上傳的方法,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09
JavaScript onclick與addEventListener使用的區(qū)別介紹
addEventListener()方法用于向指定元素添加事件句柄,使用 removeEventListener()方法來移除,onclick和addEventListener事件區(qū)別是:onclick事件會被覆蓋,而addEventListener可以先后運行不會被覆蓋,addEventListener可以監(jiān)聽多個事件2022-09-09
JavaScript獲取移動設備型號的實現(xiàn)代碼(JS獲取手機型號和系統(tǒng))
這篇文章主要介紹了JavaScript獲取移動設備型號的實現(xiàn)代碼,需要的朋友可以參考下2018-03-03
JS中注入eval, Function等系統(tǒng)函數(shù)截獲動態(tài)代碼
這篇文章主要介紹了JS中注入eval, Function等系統(tǒng)函數(shù)截獲動態(tài)代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-04-04
微信小程序?qū)崿F(xiàn)獲取自己所處位置的經(jīng)緯度坐標功能示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)獲取自己所處位置的經(jīng)緯度坐標功能,涉及微信小程序地圖功能獲取經(jīng)緯度信息的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
JS實現(xiàn)樹形結(jié)構(gòu)與數(shù)組結(jié)構(gòu)相互轉(zhuǎn)換并在樹形結(jié)構(gòu)中查找對象
這篇文章介紹了JS實現(xiàn)樹形結(jié)構(gòu)與數(shù)組結(jié)構(gòu)相互轉(zhuǎn)換并在樹形結(jié)構(gòu)中查找對象的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06

