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