IIFE (Imdiately Invoked Function Expression 當即執行的函數表達式)

函數聲明

函數聲明時必須有函數名bash

function fn(){};
複製代碼

函數表達式

函數表達式中的函數能夠爲匿名函數,也能夠有函數名,可是該函數不能直接使用,只能經過表達式左邊的變量 fn 來調用閉包

var fn = function(){};
複製代碼

看看二者區別

function a(){
    console.log("函數聲明");
}
var b = function(){
    console.log("函數表達式"); 
}
a();   //函數申明
b();   //函數表達式
複製代碼
a();   //函數聲明
b();   //報錯
function a(){
    console.log("函數聲明");
}
var b = function(){
    console.log("函數表達式"); 
}
複製代碼

爲何會有這樣的結果?
緣由: function a(){} 爲函數聲明,程序運行前就已經存在;var b = function(){} 爲函數表達式,屬於按順序執行,因此 b() 會報錯函數

進入IIFE (當即執行的函數表達式)

在ES5中,是沒有塊級做用域的概念的;咱們主要經過匿名函數的方式來塊級做用域。
用做塊級做用域(私有做用域)的匿名函數的語法:ui

(function() { //此處是塊級(私有)做用域 })();

!function () { //此處是塊級(私有)做用域  } ();   
~function () { //此處是塊級(私有)做用域  } ();   
-function () { //此處是塊級(私有)做用域  } ();   
+function () { //此處是塊級(私有)做用域  } ();   

//這些都是當即執行的函數表達式的寫法
//定義並當即調用了一個匿名函數。將函數聲明包含在一對圓括號中,表示它其實是一個函數表達式。
複製代碼
IIFE 寫法的產生:
var a = function() { console.log("IIFE 寫法的產生"); };
a();   //IIFE 寫法的產生 
//咱們將一個匿名函數賦值給了一個全局變量a,而後調用了這個函數
複製代碼
衍生出 IIFE 寫法
(function(){
    console.log("這是一個當即執行的函數");
})();
//第一個圓括號:將匿名函數轉換爲函數表達式
//第二個圓括號:當即執行匿名函數(固然,你也能夠設置一個函數名)
複製代碼

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

經常使用實例

預期: 使用 setTimeout 循環輸出 0 1 2 3 4 5code

for(var i = 0; i <= 5; i++){
    setTimeout(function timer(){
        console.log(i);
    },  i*1000);
}
//結果:1秒內輸出6個6
複製代碼

緣由: 超時的回調函數都將在循環完成以後當即運行。
解決方法:內存

方法一:
for(var i = 0; i <= 5; i++){
    (function(){
        var j = i;
        setTimeout(function timer(){
            console.log(j);
        }, j*1000)
    })();
}
//結果: 0 1 2 3 4 5
複製代碼
方法二:
for(var i = 0; i <= 5; i++){
    (function(j){
        setTimeout(function timer(){
            console.log(j);
        }, j*1000)
    })(i);
}
//結果: 0 1 2 3 4 5
複製代碼

IIFE 爲每次迭代建立了新的做用域,這給了超時回調函數一個機會在每次迭代時閉包一個新的做用域。作用域

相關文章
相關標籤/搜索