問題引入:我們寫函數,就是為了使我們的代碼更加模塊化,然後,提高代碼的重用。但是,有些函數,從定義到整個函數就運行了一遍。但是這個函數依然存在,就占用了大量的記憶體。那有沒有一種函數,執行完了之後,就不存在了的呢? 1、什麼是匿名函數 聲明一個函數,並馬上調用這個匿名函數就叫做立即執行函數;也可以說立 ...
問題引入:我們寫函數,就是為了使我們的代碼更加模塊化,然後,提高代碼的重用。但是,有些函數,從定義到整個函數就運行了一遍。但是這個函數依然存在,就占用了大量的記憶體。那有沒有一種函數,執行完了之後,就不存在了的呢?
1、什麼是匿名函數
聲明一個函數,並馬上調用這個匿名函數就叫做立即執行函數;也可以說立即執行函數是一種語法,讓你的函數在定義以後立即執行;
立即執行函數的創建步驟,看下圖:
2、立即函數形式
接下來看立即執行函數的兩種常見形式:
//匿名函數包裹在一個括弧運算符中,後面跟一個小括弧 (function(){ //... })() ////匿名函數後面跟一個小括弧,整個包裹在一個括弧運算符中 (function(){ //... }())
(),!,+,-,=等運算符都能起到立即執行的作用,這些運算符的作用就是將匿名函數或函數聲明轉換為函數表達式。
要註意兩點,一是函數體後面要有小括弧(),二是函數體必須是函數表達式而不能是函數聲明。
(function (test) { //使用()運算符,輸出123 console.log(test); })(123); (function (test) { //使用()運算符,輸出123 console.log(test); }(123)); !function (test) { //使用!運算符,輸出123 console.log(test); }(123); var fn = function (test) { //使用=運算符,輸出123 console.log(test); }(123);
3.立即執行函數好處
- 不必為函數命名,避免了污染全局變數
- 立即執行函數內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變數
- 封裝變數
總而言之:立即執行函數會形成一個單獨的作用域,我們可以封裝一些臨時變數或者局部變數,避免污染全局變數。以一個面試題為例:
var liList = ul.getElementsByTagName('li') for(var i=0; i<6; i++){ liList[i].onclick = function(){ alert(i) // 為什麼 alert 出來的總是 6,而不是 0、1、2、3、4、5 } }
為什麼 alert 的總是 6 呢,因為 i 是貫穿整個作用域的,而不是給每個 li 分配了一個 i,如下:
劃重點:用戶一定是在for運行完了之後,才點擊的,此時i為6
解決方案:
用立即執行函數給每個li創造一個獨立作用域即可(當然還有其他辦法):
var liList = ul.getElementsByTagName('li') for(var i=0; i<6; i++){ !function(ii){ liList[ii].onclick = function(){ alert(ii) // 0、1、2、3、4、5 } }(i) }
3.立即執行函數使用場景
1、你的代碼在頁面載入完成之後,不得不執行一些設置工作,比如時間處理器,創建對象等等。2、所有的這些工作只需要執行一次,比如只需要顯示一個時間。
3、但是這些代碼也需要一些臨時的變數,但是初始化過程結束之後,就再也不會被用到,如果將這些變數作為全局變數,不是一個好的註意,我們可以用立即執行函數——去將我們所有的代碼包裹在它的局部作用域中,不會讓任何變數泄露成全局變數。看如下代碼: 如果沒有被包裹在立即執行函數中,那麼臨時變數todaydom,days,today,year,month,date,day,msg都將成為全局變數(初始化代碼遺留的產物)。用立即執行函數之後,這些變數都不會在全局變數中存在,以後也不會其他地方使用,有效的避免了污染全局變數。