[javascript]當即執行函數

問題引入:咱們寫函數,就是爲了使咱們的代碼更加模塊化,而後,提升代碼的重用。可是,有些函數,從定義到整個函數就運行了一遍。可是這個函數依然存在,就佔用了大量的內存。那有沒有一種函數,執行完了以後,就不存在了的呢?面試

 

一、什麼是匿名函數

聲明一個函數,並立刻調用這個匿名函數就叫作當即執行函數;也能夠說當即執行函數是一種語法,讓你的函數在定義之後當即執行;dom

當即執行函數的建立步驟,看下圖:模塊化

 

二、當即函數形式

接下來看當即執行函數的兩種常見形式:函數

//匿名函數包裹在一個括號運算符中,後面跟一個小括號
(function(){
    //...
})()

////匿名函數後面跟一個小括號,整個包裹在一個括號運算符中
(function(){
    //...
}())

(),!,+,-,=等運算符都能起到當即執行的做用,這些運算符的做用就是將匿名函數或函數聲明轉換爲函數表達式。spa

要注意兩點,一是函數體後面要有小括號(),二是函數體必須是函數表達式而不能是函數聲明。code

(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.當即執行函數好處

  1. 沒必要爲函數命名,避免了污染全局變量
  2. 當即執行函數內部造成了一個單獨的做用域,能夠封裝一些外部沒法讀取的私有變量
  3. 封裝變量

總而言之:當即執行函數會造成一個單獨的做用域,咱們能夠封裝一些臨時變量或者局部變量,避免污染全局變量。以一個面試題爲例:對象

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  liList[i].onclick = function(){
    alert(i) // 爲何 alert 出來的老是 6,而不是 0、一、二、三、四、5
  }
}

爲何 alert 的老是 6 呢,由於 i 是貫穿整個做用域的,而不是給每一個 li 分配了一個 i,以下:blog

 

劃重點:用戶必定是在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、一、二、三、四、5
    }
  }(i)
}

 

4.當即執行函數使用場景

一、你的代碼在頁面加載完成以後,不得不執行一些設置工做,好比時間處理器,建立對象等等。
二、全部的這些工做只須要執行一次,好比只須要顯示一個時間。
三、可是這些代碼也須要一些臨時的變量,可是初始化過程結束以後,就不再會被用到,若是將這些變量做爲全局變量,不是一個好的注意,咱們能夠用當即執行函數——去將咱們全部的代碼包裹在它的局部做用域中,不會讓任何變量泄露成全局變量。看以下代碼:
若是沒有被包裹在當即執行函數中,那麼臨時變量todaydom,days,today,year,month,date,day,msg都將成爲全局變量(初始化代碼遺留的產物)。用當即執行函數以後,這些變量都不會在全局變量中存在,之後也不會其餘地方使用,有效的避免了污染全局變量。
相關文章
相關標籤/搜索