JS中的IIFE

IIFE

IIFE: Immediately Invoked Function Expression,翻譯過來就是當即調用的函數表達式。也就是說,在函數聲明的同時當即調用這個函數。javascript

普通的函數聲明和函數調用java

function bar() {
    var a = 10;
    console.log(a);
}
bar(); // 函數調用
複製代碼

IIFE函數聲明和調用bash

(function foo(){
    var a = 10;
    console.log(a);
})();
複製代碼

首先注意一點的就是IIFE函數是由一對()將函數聲明包裹起來的表達式。使得JS編譯器再也不認爲這是一個函數聲明,而是一個IIFE,即馬上執行函數表達式。 可是二者達到的目的都是同樣的,都是聲明瞭一個函數而且隨後調用這個函數。微信

爲何要使用IIFE

若是隻是爲了當即執行一個函數,顯然IIFE所帶來的好處有限。實際上,IIFE的出現是爲了彌補JS在scope方面的缺陷:JS只有全局做用域(global scope)、函數做用域(function scope),從ES6開始纔有塊級做用域(block scope)。對比如今流行的其餘面向對象的語言能夠看出,JS在訪問控制這方面是多麼的脆弱!那麼如何實現做用域的隔離呢?在JS中,只有function才能實現做用域隔離,所以若是要將一段代碼中的變量、函數等的定義隔離出來,只能將這段代碼封裝到一個函數中。markdown

爲調用一次的函數達到做用域隔離、命名衝突、減小內存佔用問題。閉包

塊級做用域

在ES5中是沒有塊級做用域的概念。只有全局做用域和函數做用域函數

for (var i = 0; i< 10; i++) {
    console.log(i);
}
console.log(i); // 10
複製代碼

這個地方能夠看出for循環中的變量i是一個全局變量,在for循環執行完畢後這個i仍是能夠訪問到的。i並無被銷燬spa

塊級做用域也能夠稱爲私有做用域。也就是說只在for循環的語句塊中有定義,一旦循環結束,變量i就會被銷燬,而在ES5中咱們主要使用匿名函數【IIFE】的方式來達到塊級做用域的效果。翻譯

IIFE實現做用域隔離
// 函數聲明語句寫法
function test() {};
test();

// 函數表達式寫法
var test = function(){};
test();
複製代碼

[注意]javascript引擎規定,若是function關鍵字出如今行首,一概解釋成函數聲明語句;而函數聲明後面是不能跟圓括號的(匿名函數是函數聲明的一種)。然而,函數表達式的後面能夠跟圓括號。因此能夠將函數聲明轉換成函數表達式。 在當即執行函數中,定義的變量會在當即code

因此,解決方法就是不要讓function出如今行首,讓引擎將其理解成一個表達式 最經常使用的幾種辦法

(function(){
    console.log('123');
}());

(function(){
    console.log('123');
})();

(function foo(){
    console.log('123');
})();
複製代碼
分號

對於當即執行函數末尾的;分號,最好加上,由於若是不加,遇到兩個都是用括號()包裹執行的IIFE時,就會遇到問題。

(function(){
    console.log('a');
})()

(function(){
    console.log('b');
})()
複製代碼

這一段代碼只有a能夠顯示出來,b會報錯

TypeError: (intermediate value)(...) is not a function

不加分號,上面的內容會被JS理解爲:

(function(){
    console.log('a');
})()(function(){
    console.log('b');   
 })()
複製代碼

也就是說,a匿名函數執行後,沒有;的隔斷,後面的b當即執行函數與a合成了一個函數。執行到輸出完a時,沒有reutrn,後面的()至關於對undefined進行了執行,因此報錯。

咱們能夠這樣修改

(function(){
    console.log('a');
})()

(function(){
    console.log('b');
}())

複製代碼

這樣修改後,a,b都會顯示出來,可是一樣會報錯, 還有其餘的修改方式,可是我建議加上;分號避免報錯。

IIFE的優勢

  • 建立塊級(私有)做用域,避免了向全局做用域中添加變量和函數,所以也避免了多人開發中全局變量和函數的命名衝突。
  • IIFE中定義的任何變量和函數,都會在執行結束時被銷燬,這種作法能夠減小閉包占用的內存問題,由於沒有指向匿名函數的引用。只要函數執行完畢,就能夠當即銷燬其做用域鏈了。

歡迎關注微信公衆號

相關文章
相關標籤/搜索