技術頻道導航
HTML/CSS
.NET技術
IIS技術
PHP技術
Js/JQuery
Photoshop
Fireworks
服務器技術
操作系統(tǒng)
網(wǎng)站運營

贊助商

分類目錄

贊助商

最新文章

搜索

【示例】講解JavaScript IIFE 與函數(shù)調(diào)用

作者:admin    時間:2022-6-9 1:2:28    瀏覽:

在JavaScript的函數(shù)調(diào)用時,常常見到 IIFE 這個詞,它其實是“立即調(diào)用函數(shù)表達式”的英文縮寫,在本文中,我將介紹什么是 IIFE,它與調(diào)用函數(shù)又有什么關系。

我們先看一個簡單的函數(shù)調(diào)用示例,隨后再介紹 IIFE 與函數(shù)調(diào)用的關系。

function hello(name) {
  return 'Hello ' + name + '!';
}
// 函數(shù)調(diào)用
const message = hello('World');

hello('World')就是一個函數(shù)調(diào)用。

何為函數(shù)調(diào)用?

我們可以這樣定義:

當計算結(jié)果為函數(shù)對象的表達式,后跟一對括號(),括號內(nèi)用逗號,分隔的參數(shù)表達式列表時,這就是函數(shù)調(diào)用。例如 parseInt('18')。

上面示例中,hello表達式計算為一個函數(shù)對象,后跟一對帶World參數(shù)的括號()。

函數(shù)調(diào)用表達式不能是屬性訪問器 obj.myFunc() ,這是方法調(diào)用,例如[1,5].join(',')不是函數(shù)調(diào)用,而是方法調(diào)用。請記住它們之間的區(qū)別。

函數(shù)調(diào)用示例

function myFunction(a, b) {
  return a * b;
}
myFunction(10, 2);   // 20

上面的函數(shù)不屬于任何對象。

在瀏覽器中,頁面對象是瀏覽器窗口。上面的函數(shù)自動變成了窗口函數(shù)。因此,myFunction()window.myFunction() 是同一個函數(shù):

function myFunction(a, b) {
  return a * b;
}
window.myFunction(10, 2);    // 20

何為 IIFE?

IIFE全稱是立即調(diào)用函數(shù)表達式(英文:immediately-invoked function expression,縮寫:IIFE),IIFE 也是一個函數(shù)調(diào)用。讓我們看一個 IIFE 的簡單例子:

// IIFE
const message = (function(name) {
  return 'Hello ' + name + '!';
})('World');

第一對括號(function(name) {...})是計算結(jié)果為函數(shù)對象的表達式,然后是一對帶'World'參數(shù)的括號:('World')。

IIFE 用法

立即調(diào)用函數(shù)表達式擁有數(shù)種不同的寫法。最常見的一種是將函數(shù)表達式字面量至于圓括號(分組運算符)之內(nèi),然后使用圓括號調(diào)用函數(shù)。

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

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

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

開頭的括號可能會因為解釋器的分號自動插入特性造成一些問題。括號本用于明確字面量為表達式以與函數(shù)聲明語句區(qū)分,但解釋器可能將括號解釋為對以上一行中結(jié)尾的變量名為名的函數(shù)的調(diào)用。在一些省略分號的程序中,可見將分號至于行首的做法。這樣的分號被稱為“防御性分號”,舉例:

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

如此書寫,以防止語句被理解為對函數(shù)c的調(diào)用(c(...))。

IIFE 例子

理解立即調(diào)用函數(shù)表達式的關鍵在于認清JavaScript擁有函數(shù)作用域,但沒有塊作用域(ES6之前),且通過指針(而非復制)將變量傳入一個函數(shù)閉包。 ES6 引入了新關鍵字 letconst,用它們定義的常量和變量具有塊級作用域。

求值上下文(Evaluation context)

缺少塊作用域意味著一個在類似于for循環(huán)的塊中聲明的變量會被置頂?shù)狡渌暮瘮?shù)中。如果一個內(nèi)部函數(shù)依賴于一個外部變量,而該外部變量被外部函數(shù)更改,那么執(zhí)行內(nèi)函數(shù)就有些困難。舉例,我們在聲明函數(shù)之后,但在定義函數(shù)之前,改變一個變量的值。

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

當我們手動給v賦值時這結(jié)果似乎沒什么問題。不過,如果getValue()是在一個循環(huán)中被定義的,那么就可能出現(xiàn)預想外的結(jié)果。

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

getValue(); // 1

此例中,函數(shù)將 v 作為參數(shù)傳入并立即調(diào)用,保護了內(nèi)部函數(shù)的執(zhí)行上下文。

利用IIFE創(chuàng)建真正的私有函數(shù)和變量,并用閉包訪問

立即調(diào)用函數(shù)表達式也可以用來創(chuàng)建私有方法來訪問函數(shù),不僅起到保護作用,同時也暴露了一些可以后續(xù)使用的屬性。

// 'counter' 函數(shù)返回一個具有屬性的對象, 這里的屬性就是
// get set等函數(shù)
var counter = (function(){
  var i = 0;

  return {
    get: function(){
      return i;
    },
    set: function( val ){
      i = val;
    },
    increment: function() {
      return ++i;
    }
  };
})();
// 這些調(diào)用使用了剛才counter得到的屬性
counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5

如果我們試圖從全局作用域直接訪問 counter.i ,會得到 undefined,因為 i 這個數(shù)據(jù)由 IIFE 封裝,它并不是 counter的屬性。同樣的,如果我們試圖訪問 i 也會收到錯誤,因為 i 并沒有在全局作用域中定義。

總結(jié)

本文介紹了JavaScript中的 IIFE 與函數(shù)調(diào)用,通過本文的學習,我們應該了解了函數(shù)調(diào)用的定義,知道 IIFE 也是函數(shù)調(diào)用的一種。

相關文章

相關文章
    x
    • 站長推薦
    /* 左側(cè)顯示文章內(nèi)容目錄 */