1. 定義
IIFE: Immediately Invoked Function Expression,意為立即呼叫的函式運算式,也就是說,宣告函式的同時立即呼叫這個函式,
對比一下,這是不采用IIFE時的函式宣告和函式呼叫:
function foo(){
var a = 10;
console.log(a);
}
foo();
下面是IIFE形式的函式呼叫:
(function foo(){
var a = 10;
console.log(a);
})();
函式的宣告和IIFE的區別在于,在函式的宣告中,我們首先看到的是function關鍵字,而IIFE我們首先看到的是左邊的(,也就是說,使用一對()將函式的宣告括起來,使得JS編譯器不再認為這是一個函式宣告,而是一個IIFE,即需要立刻執行宣告的函式,
兩者達到的目的是相同的,都是宣告了一個函式foo并且隨后呼叫函式foo,
2. 為什么需要IIFE?
如果只是為了立即執行一個函式,顯然IIFE所帶來的好處有限,實際上,IIFE的出現是為了彌補JS在scope方面的缺陷:JS只有全域作用域(global scope)、函式作用域(function scope),從ES6開始才有塊級作用域(block scope),對比現在流行的其他面向物件的語言可以看出,JS在訪問控制這方面是多么的脆弱!那么如何實作作用域的隔離呢?在JS中,只有function,只有function,只有function才能實作作用域隔離,因此如果要將一段代碼中的變數、函式等的定義隔離出來,只能將這段代碼封裝到一個函式中,
在我們通常的理解中,將代碼封裝到函式中的目的是為了復用,在JS中,當然宣告函式的目的在大多數情況下也是為了復用,但是JS迫于作用域控制手段的貧乏,我們也經常看到只使用一次的函式:這通常的目的是為了隔離作用域了!既然只使用一次,那么立即執行好了!既然只使用一次,函式的名字也省掉了!這就是IIFE的由來,
3. IIFE的常見形式
根據最后表示函式執行的一對()位置的不同,常見的IIFE寫法有兩種,示例如下:
串列1:IIFE寫法一
(function foo(){
var a = 10;
console.log(a);
})();
串列2:IIFE寫法二
(function foo(){
var a = 10;
console.log(a);
}());
這兩種寫法效果完全一樣,使用哪種寫法取決于你的風格,貌似第一種寫法比較常見,
其實,IIFE不限于()的表現形式[1],但是還是遵守約定俗成的習慣比較好,
4. IIFE的函式名和引數
根據《You Don’t Know JS:Scope & Clouses》[2]的說法,盡量避免使用匿名函式,但是IIFE確實只執行一次,給IIFE起個名字有些畫蛇添足了,如果非要給IIFE起個名字,干脆就叫IIFE好了,
IIFE可以帶(多個)引數,比如下面的形式:
var a = 2;
(function IIFE(global){
var a = 3;
console.log(a); // 3
console.log(global.a); // 2
})(window);
console.log(a); // 2
5. IIFE構造單例模式
JS的模塊就是函式,最常見的模塊定義如下:
function myModule(){
var someThing = "123";
var otherThing = [1,2,3];
function doSomeThing(){
console.log(someThing);
}
function doOtherThing(){
console.log(otherThing);
}
return {
doSomeThing:doSomeThing,
doOtherThing:doOtherThing
}
}
var foo = myModule();
foo.doSomeThing();
foo.doOtherThing();
var foo1 = myModule();
foo1.doSomeThing();
如果需要一個單例模式的模塊,那么可以利用IIFE:
var myModule = (function module(){
var someThing = "123";
var otherThing = [1,2,3];
function doSomeThing(){
console.log(someThing);
}
function doOtherThing(){
console.log(otherThing);
}
return {
doSomeThing:doSomeThing,
doOtherThing:doOtherThing
}
})();
myModule.doSomeThing();
myModule.doOtherThing();
6. 小結
IIFE的目的是為了隔離作用域,防止污染全域命名空間,
ES6以后也許有更好的訪問控制手段(模塊?類?),有待研究,
參考
1.Ben Alman, “Immediately-Invoked Function Expression (IIFE)“.
2.Kyle Simpson, You Don’t Know JS:Scope & Clouses (, 2014).
原文地址:http://softlab.sdut.edu.cn/blog/subaochen/2016/02/說一說js的iife/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/228863.html
標籤:JavaScript
上一篇:JavaScript的書寫位置
下一篇:微信小程式:音樂播放器
