關於 Closure / lexical scope


Posted by hoyi-23 on 2021-10-24

Lexical Scope

認識Closure前,要先知道 Lexical Scope!
Lexical Scope 定義函式與其可使用的變數範圍
若fn2包在fn1內,fn2可以使用fn1的變數,這就是fn2的Lexical Scope。

子層可以拿父層,父層無法拿子層。

Lexical Scope範例:

// global scope
let x = 1;
const parentFunction = ()=>{
    //local scope
    let y = 2;
    console.log(x);
    console.log(y);

    const childFunction = ()=>{
        console.log(x += 5);
        console.log(y += 1);
    }
    childFunction(); //6,3
}
parentFunction();// 1,2

可以說,childFunction在parentFunction中有Closure,因為ChildFunction可以拿取外層(也就是parentFunction)的變數,但是Lexical Scope不是代表Closure,只算是Closure中重要的一部份。


Closure

Closure 在我們定義函式時就已經出現,不是在執行時才出現。
前面說 Lexical Scope 是Closure重要的一部分,那另一部份呢?
Closure: 一個函式可以取得父層的scope,即使父層已經執行結束

如何讓子層函式可以繼續取得父層scope,就算父層已經結束執行呢?
我們可以修改上一個範例:
將原本執行childFunction的地方,改為回傳 childFunction本身。

// global scope
let x = 1;
const parentFunction = ()=>{
    //local scope
    let y = 2;
    console.log(x);
    console.log(y);

    const childFunction = ()=>{
        console.log(x += 5);
        console.log(y += 1);
    }
    return childFunction;
}
const result = parentFunction();//1,2
console.log(result);
//()=>{console.log(x += 5);console.log(y += 1);}
result(); //6,3
result(); //11,4
console.log(x); //11
console.log(y); //reference error, private variable

筆記: 立即執行函式(IIFE)的理解與運用

Closure 和 IIFE

const increment = (()=>{
    let counter = 0;
    console.log(`counter ${counter}`);
    const credit = (num) => console.log(`I have ${num} credit(s).`);
    return ()=>{conter++; credit(counter)}
})(); 
// counter 0

increment(); // I have 1 credit(s).
increment(); // I have 2 credit(s).

Closure 、 IIFE 和 參數

const credits = ((num)=>{
    let credits = num;
    console.log(`initial credits value:` ${credits});
    return ()=>{
        credit -= `;
        if(credits > 0){
        console.log(`playing game, ${credits} credits remaining`)
        };
        if(credits <= 0){
        console.log(`not enough credits`)
        }
    }
})(3); // initial credits value: 3

cresits() // playing game,2 credits remaining
cresits() // playing game,1 credits remaining
cresits() // not enough credits

#closure #IIFE #lexical #scope







Related Posts

JS30 Day 6 筆記

JS30 Day 6 筆記

Ruby:  Exception Handling

Ruby: Exception Handling

不用dynamic dns,使用ssh連上非固定IP的linux電腦

不用dynamic dns,使用ssh連上非固定IP的linux電腦


Comments