什么是立即執行函數
聲明一個函數,並馬上調用這個匿名函數就叫做立即執行函數。在定義好一個函數后,直接執行。
(function() {alert('立即執行函數')})()
用聲明一個函數,用括號包起來,調用此函數。
立即執行函數的寫法
有時候,我們定義函數以后,立即調用該函數,這時不能在函數的定義后面直接加圓括號,這會產生語法錯誤。產生語法錯誤的原因是,function這個關鍵字,既可以當做語句,也可以當做表達式。
//語句
function fn() {};
//表達式
var fn = function(){};
規定:如果function出現在行首,一律解析成語句。行首是function關鍵字時,這一段都是函數定義,不應該以圓括號結尾,所以會報錯。當不讓function出現在行首時,這將被理解為一個表達式,最簡單的處理方式就是將其放在一個圓括號里。
(function() {
...
}())
(function() {
...
})()
以圓括號開頭,這將被理解為表達式,而不是一個函數定義語句,所以就避免了錯誤,這就叫“立即執行函數”。
其他的寫法:
(function() {alert('匿名函數')}()) //用括號將整個表達式包起來
(function() {alert('匿名函數')})() //用括號將函數包起來
!function() {alert('匿名函數')}()
+function() {alert('匿名函數')}()
-function() {alert('匿名函數')}()
~function() {alert('匿名函數')}()
void function() {alert('匿名函數')}()
new function() {alert('匿名函數')}()
立即執行函數的作用
1、不必為函數命名,避免了污染全局變量。
2、立即執行函數內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。
3、封裝變量。
面試題
var list = document.getElementById("list");
var li = list.children;
for(var i = 0 ;i<li.length;i++){
li[i].onclick=function(){
alert(i); // 結果總是3.而不是0,1,2
}
}
因為i是貫穿整個作用域的,而不是給每一個li分配一個i,點擊事件使異步用戶一定是在for運行完以后才點擊,此時i已經變成3了。
解決方法:
1、使用立即執行函數,給每個li創建一個獨立的作用域,在立即執行函數執行的時候,i的值從0到2,對應三個立即執行函數,所以就能正常輸出了。
var list = document.getElementById("list");
var li = list.children;
for(var i = 0 ;i<li.length;i++){
(function(j) {li[j].onclick=function(){
alert(j); // 結果是0,1,2
}})(i)
}
2、使用ES6的塊級作用域:
var list = document.getElementById("list");
var li = list.children;
for(let i = 0 ;i<li.length;i++){
li[i].onclick=function(){
alert(i); // 結果總是3.而不是0,1,2
}
}
立即執行函數的使用場景
1、代碼在頁面加載完成之后,不得不執行一些設置工作,比如時間處理器,創建對象等等。
2、所有的這些動作只需要執行一次,比如只需要顯示一個事件。
3、將代碼包裹在它的局部作用域中,不會讓任何變量泄漏成全局變量。
立即執行函數的參數
(function(i) {
...
})(j)
如果立即執行函數中需要全局變量,全局變量會被作為一個參數傳遞給立即執行函數。j代表是實參,i代表的是執行函數的形參。
立即執行函數的作用
1、改變變量的作用域(創建一個獨立的作用域)。
2、封裝臨時變量。