[07] JavaScript 入門 - 函式、即刻調用的函式運算式、閉包


keywords:function,IIFE,closure

函式 ( Function )

作為值的函式

function abc() {...}

  • abc 基本上是位於外層包圍範疇中( 這邊是全域 )的一個變數,它被賦予所宣告的 function 的一個參考, ∴這個 function 本身是一個值,就像 90 或 [4,5,6]。

  • 我們可以將一個值傳給一個函式( 也就是傳參數 )
    ex:

      function abc(s) { 
          console.log(s); 
      }
      abc('hi'); // hi
    
  • 函式本身也能指定給變數,或是被傳入其他函式,又或者被其他函式回傳
    ex:
      const abc = function (){...}  // 匿名函式運算式 指定給常數 abc
      const p = function aaa (){...} // 具名函式運算式 指定給常數 p
    

即刻調用的函式運算式 ( Immediately Invoked Function Expression,IIFE )

  • 執行一個運算式除了先宣告後再調用,像這樣 abc();,而另外一種方式是即刻調用的函式運算式
      (function abc(){
          console.log('hi');
      })();
      // 'hi'
    
  • 圍繞在最外層的(也就是範例粗體的部分),是 JavaScript 的文法,作用是避免被視為一個普通的函式宣告。
    ( function abc() {...} )();

  • 而最後的()會實際執行前面所參考的函式運算式
    ( function abc() {...} )();

  • IIFE 是一個函式,而函式會建立變數範疇,通常是為了宣告不會影響到 IIFE 外部程式碼的變數

    const q = (function abc(){
        return 99;
    })();
    q; // 99
    abc(); // ReferenceError
    

    這裡的意思是執行名為 abc 的函式,並把回傳值指定給 q

閉包 ( Closure )

閉包是 JavaScript 很重要的一環,幾乎很多面試題都會考這個,但這邊只會簡單的介紹,詳細的筆記會在後面整理。

執行完一個函式,還能繼續存取函式範疇裡的變數的一種方式。
先看範例:

    function f1() {
      let a = 1;

      function showA() {
        console.log(a);
      }
      return showA;
    }

這邊 f1 是一個函式,執行後會先宣告並賦值 1 給變數 a,然後宣告一個 showA 函式在自己的範疇內,並回傳這個 showA 函式。 OK clear 👌

    let result = f1();
    result; // ƒ showA(){
                console.log(a);
              }

    result(); // 1
    a; // Uncaught ReferenceError: a is not defined
  • 我們現在可以在全域範疇中印出 a ,都是因為 f1 回傳了一個 showA 函式,而因為 showA 有參考到 a 所以我們才可以印出 a
  • 如果只單印出 a 會得到一個 ReferenceError,因為所在的全域範疇中並沒有變數 a
#function #IIFE #closure