iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 14

13. 關於 IIFE 的 4 題練習

IIFE 立即函式


定義

IIFE (Immediately Invoked Function Expression) 是在宣告完函式後馬上執行的一種函式

示例

這裡嘗試把一般的函式呼叫,改寫成匿名函式:

// original
function greeting() { console.log("Hi"); }
greeting();

// IIFE
(function () { console.log("Hi"); })();

這種形式包含

  1. 用 Grouping operator () 包起來的匿名函式(anonymous function)。
  2. 在 Grouping operator () 後用expression () 執行函式。

即使不是宣告匿名函式,也可以正常運行,只是沒什麼意義:

(function greeting() { console.log("Hi"); })();
// output: "Hi"

IIFE 的用途,通常是 避免變數汙染到global scope

(function () { 
    var name = "apple";
    return name;
})();

console.log(name);
// output: "" ( in browser )

→ 因為在函式內宣告的變數只有function scope,因此不會影響到全域變數。

  • 延伸問題: 為什麼保持網站的全域(global scope)原樣是一個好做法?
    我想了兩種可能:
    1. 基於開發者自身的立場,因為 全域變數在任何位置都可以被呼叫,會很容易造成變數混亂。 像是原本要在function裡使用的一個變數,但沒有定義到,結果function自己找不到變數只好往外找(scope chain),可能就會影響全域變數,那後續的程式碼會全部亂掉。
    2. 基於合作的他人立場,大概是便於程式碼的維護。就像使用bootstrap或其他modules時,工程師在開發網頁的認知一定都是基於原始定義,如果原始定義的全域變數被修改了,會造成其他工程師在合作和維護上的不便。
      (如果有錯拜託洗臉我QQ我會非常感激。)

如果把 IIFE 指派給變數,會儲存回傳值,不會儲存 function 本身:

let hi = (function () { 
    let hi = "Hi!!";
    return hi;
})();

console.log(hi);  
// output: Hi!!

例題

  1. 解釋下列程式碼為什麼不是IIFE: function foo(){ }();. (Immediately Invoked Function Expression,立即函式) (題目來自 前端工程師面試問題集 ★ Front-end Job Interview Questions)
    • 需要修改那裡使它成為IIFE?

Ans. 不是, function foo(){ }() → (function foo(){ })(); 在function外加上(小括號),foo可以刪除。

  1. 下面的兩個 alerts 的結果會是什麼?
    (題目來自 前端工程師面試問題集 ★ Front-end Job Interview Questions)
var foo = "Hello";
(function() {
  var bar = " World";
  alert(foo + bar);
})();
alert(foo + bar);

Ans. "Hello World" ; (錯誤訊息)ReferenceError: bar is not defined

  1. 底下程式碼是否為正確呢?
    a. 出現錯誤
    b. 不會出現錯誤
    (題目來自 六角學院觀念測驗:JavaScript 熱門面試題。)
var a = 1
(function(){console.log(a);})()  

Ans. 出現錯誤, 程式碼沒有斷句,1會被當成function呼叫。
可以看成這樣:

var a = 1(function(){console.log(a);})() 
// TypeError: 1 is not a function

4.請問以下立即函式會出現什麼訊息?
(題目來自 六角學院觀念測驗:JavaScript 熱門面試題。)

(function(){
    console.log('六角學院 A'); 
}());

(function(){
    console.log('六角學院 B');
});

Ans. 六角學院 A / (){ console.log('六角學院 B'); }
第一個答案會執行,是因為符合 JSLint 的版本。
第二個答案則是只包裹了function但沒有執行,所以回傳了整個function。

【如內文有誤還請不吝告知>< 謝謝閱覽至此的各位:D】

參考資料:

-----正文結束-----

非同步請求是我的罩門,所以前幾天的文章都看資料看得很痛苦。
今天寫IIFE整個加速而且快樂很多。
BTW 昨天的文章有補充fetch API的部分,有興趣可以回去看看。


上一篇
12. 使用 async & await (Fetch API)
下一篇
14. 解釋 Event bubbling & Event delegation
系列文
登堂入室!前端工程師的觀念技術 _30_ 題23

尚未有邦友留言

立即登入留言