Closure
閉包可以保存函式內的變數,無法存函式外改變變數的值,並應用到巢狀函式內。
A couple of questions
// 函式使用外部變數,會使用最新的值嗎?
let name = "John";
function sayHi() {
alert("Hi, " + name);
}
name = "Pete";
sayHi(); // what will it show: "John" or "Pete"?
// 函式會使用內部變數還是外部變數?
function makeWorker() {
let name = "Pete";
return function() {
alert(name);
};
}
let name = "John";
// create a function
let work = makeWorker();
// call it
work(); // what will it show? "Pete" (name where created) or "John" (name where called)?Lexical Environment
在 JavaScript 裡,每個函式、{...}、整個程式碼都有內部物件叫 Lexical Environment。有 2 個部分
Environment Record 一個物件儲存所有區域變數當作屬性
指向外部 lexical environment
變數只是一個 Environment Record 的屬性,取得或改變變數意思是取得或改變物件的屬性。


Function Declaration
函式在 Lexical Environment 被創造的時候就已經被宣告,變數是在執行到時才被創造。這是為什麼可以在函式宣告前使用。

Inner and outer Lexical Environment

當使用函式時,會創造 2 個 Lexical Environment, inner Lexical Environment 的屬性有帶入該函式的參數,outer Lexical Environment 有全域變數包含函式本身及用到的全域變數。當函式使用變數時,會先在內部尋找,然後尋找外部,然後是全域變數。在 "use strict" 下,變數未定億會出現錯誤,非 "use strict",會指定變數值為 undefined。

Nested functions

Environments in detail
1. 腳本開始時只有全域 Lexical Environment,裡面只有宣告 makeCounter(),所有函式宣告的時候,必然有一個隱藏的屬性 [[Environment]] 指向函式,

2. 呼叫函式的時候,創造 Lexical Environment,Environment Record 儲存區域變數,指向外部 lexical reference 被設定成 [[Environment]] 屬性的函式。

3. 執行到巢狀函式時,創造 [[Environment]] 屬性外部指向 makeCounter()。

4. makeCounter() 執行完畢,結果儲存在全域變數 counter,當 counter 被呼叫執行 return count++ 這行程式碼。

5. 雖然 makeCounter() 執行完畢,但仍有 [[Environment]] 屬性指向他,因此呼叫 counter() 時,會先創造一個空的 Lexical Environment 因為沒有參數,再來指向外部的 [[Environment]] 。

6. 呼叫 counter(),不只返回 count 值,也增加他的值。

開頭問題的解答:

Code blocks and loops, IIFE
閉包的特性可以應用在任何 {...} 上。
if

for
Code blocks
IIFE
Garbage collection
Real-life optimizations
Last updated
Was this helpful?