首頁>技術>

簡介

立即呼叫函式表示式( IIFE)是一個在定義時就會立即執行的 JavaScript 函式。有時也被叫做“自執行(匿名)函式”。

程式碼結構如下:

(function () {    statements})();

這是一個被稱為自執行匿名函式 的設計模式,主要包含兩部分。

第一部分是包圍在圓括號運算子 () 裡的一個匿名函式,這個匿名函式擁有獨立的詞法作用域。這不僅避免了外界訪問此 IIFE 中的變數,而且又不會汙染全域性作用域。

第二部分再一次使用 () 建立了一個立即執行函式表示式,JavaScript 引擎到此將直接執行函式。

用途

立即呼叫函式表示式可以令其函式中宣告的變數繞過JavaScript的變數置頂宣告規則,還可以避免新的變數被解釋成全域性變數或函式名佔用全域性變數名的情況。與此同時它能在禁止訪問函式內宣告變數的情況下允許外部對函式的呼叫。

不必為函式命名,避免了汙染全域性變數立即執行函式內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變數封裝變數用法

立即呼叫函式表示式擁有數種不同的寫法。

最常見的一種是將函式表示式字面量至於圓括號(分組運算子)之內,然後使用圓括號呼叫函式。

示例如下:

(function() {  // 這裡的語句將獲得新的作用域})();

若要將作用域外變數傳遞進函式,則按下述方式書寫:

(function(a, b) {  // a == 'hello'  // b == 'world'})('hello', 'world');

開頭的括號可能會因為直譯器的分號自動插入特性造成一些問題。括號本用於明確字面量為表示式以與函式宣告語句區分,但直譯器可能將括號解釋為對以上一行中結尾的變數名為名的函式的呼叫。

在一些省略分號的程式中,可見將分號至於行首的做法。這樣的分號被稱為“防禦性分號”。

示例程式碼如下:

a = b + c;(function() {  // 故意將分號放在這裡  // 程式碼})();

這樣的寫法,以防止語句被理解為對函式c的呼叫(c(...))。

示例講解

理解立即呼叫函式表示式的關鍵在於認清JavaScript擁有函式作用域,但沒有塊作用域(ES6之前),且透過指標(而非複製)將變數傳入一個函式閉包。ES6 引入了新的關鍵字 let和 const,用它們定義的常量和變數具有塊級作用域。

求值的上下文

缺少塊作用域意味著一個在類似於for迴圈的塊中宣告的變數會被置頂到其所包含的函式中。如果一個內部函式依賴於一個外部變數,而該外部變數被外部函式更改,那麼執行內函式就有些難點。舉例,我們在宣告函式之後,但在定義函式之前,改變一個變數的值。

var v, getValue;v = 1;getValue = function() { return v; };v = 2;getValue(); // 2

當我們手動給v賦值時這結果似乎沒什麼問題。不過,如果getValue()是在一個迴圈中被定義的,那麼就可能出現預想之外的結果。

var v, getValue;v = 1;getValue = (function(x) {  return function() { return x; };})(v);v = 2;getValue(); // 1

此例中,function將 v 作為引數傳入並立即呼叫,保護了內部函式的執行上下文。

建立真正的私有函式和變數,並用閉包訪問

立即呼叫函式表示式也可以用來建立私有方法來訪問函式,不僅起到保護作用,同時也暴露了一些可以後續使用的屬性。

// 'counter' 函式返回一個具有屬性的物件, 這裡的屬性就是// get set等函式var counter = (function(){  var i = 0;  return {    get: function(){      return i;    },    set: function( val ){      i = val;    },    increment: function() {      return ++i;    }  };})();// 這些呼叫使用了剛才counter得到的屬性counter.get(); // 0counter.set( 3 );counter.increment(); // 4counter.increment(); // 5

如果我們試圖從全域性作用域直接訪問 counter.i ,會得到 undefined,因為 i 這個資料由立即呼叫函式表示式封裝,它並不是 counter的屬性。同樣的,如果我們試圖訪問 i 也會收到錯誤,因為 i 並沒有在全域性作用域中定義。

9
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 各個方面都離不開的websocket,只是你沒有注意到