<star />

ν΄λ‘œμ € (Closure) λ³Έλ¬Έ

JavaScript πŸ“

ν΄λ‘œμ € (Closure)

별깅 2022. 12. 8. 12:47
728x90

 

ν΄λ‘œμ €λŠ” ν•¨μˆ˜μ™€ κ·Έ ν•¨μˆ˜κ°€ μ„ μ–Έλœ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ 쑰합이닀. 🌟

A closure is the combination of a function and the lexical environment within which that function was declared.

 

λͺ¨λ“  ν•¨μˆ˜ν˜• μ–Έμ–΄κ°€ κ°€μ§€κ³  μžˆλŠ” κ°€μž₯ μ€‘μš”ν•œ νŠΉμ„±μž„.

μŠ€μ½”ν”„μ˜ 속성을 ν™œμš©ν•œ μƒμœ„/μ™ΈλΆ€ μ‹λ³„μžλ₯Ό 접근함. (은닉성과 μŠ€μ½”ν”„ 체인 μ œμ–΄)

 

 

1) λ ‰μ‹œμ»¬ μŠ€μ½”ν”„

 

- μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” λ ‰μ‹œμ»¬ μŠ€μ½”ν”„λ₯Ό λ”°λ₯΄λŠ” ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ‹€.

- μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν•¨μˆ˜λ₯Ό μ–΄λ””μ„œ ν˜ΈμΆœν–ˆλŠ”μ§€κ°€ μ•„λ‹ˆλΌ, ν•¨μˆ˜λ₯Ό 어디에 μ •μ˜ν–ˆλŠ”μ§€μ— 따라 μƒμœ„ μŠ€μ½”ν”„λ₯Ό 결정함.

이λ₯Ό λ ‰μ‹œμ»¬ μŠ€μ½”ν”„ (정적 μŠ€μ½”ν”„)라 ν•œλ‹€.

 

const x = 1;

function foo() {
    const x = 10;
    bar();
}

function bar() {
    console.log(x);
}

foo();	//1
bar();	//1

 

- ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” ν•¨μˆ˜λ₯Ό μ–΄λ””μ„œ μ •μ˜ν–ˆλŠλƒμ— 따라 κ²°μ •λ˜λ―€λ‘œ, foo ν•¨μˆ˜μ™€ bar ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” 전역이닀.

- ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” ν•¨μˆ˜λ₯Ό μ •μ˜ν•œ μœ„μΉ˜μ— μ˜ν•΄ μ •μ μœΌλ‘œ κ²°μ •λ˜κ³  λ³€ν•˜μ§€ μ•ŠμŒ.

- μŠ€μ½”ν”„μ˜ μ‹€μ²΄λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ΄λ‹€<<< λ ‰μ‹œμ»¬ ν™˜κ²½μ€ μžμ‹ μ˜ "μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘° (Outer Lexical Environment Reference) λ₯Ό 톡해 μƒμœ„ λ ‰μ‹œμ»¬ ν™˜κ²½κ³Ό μ—°κ²°λœλ‹€! 이것이 λ°”λ‘œ μŠ€μ½”ν”„ 체인이닀.

 

- 즉, λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ "μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°" 에 μ €μž₯ν•  μ°Έμ‘°κ°’, μƒμœ„ μŠ€μ½”ν”„μ— λŒ€ν•œ μ°Έμ‘°λŠ” ν•¨μˆ˜ μ •μ˜κ°€ ν‰κ°€λ˜λŠ” μ‹œμ μ— ν•¨μˆ˜κ°€ μ •μ˜λœ ν™˜κ²½(μœ„μΉ˜) 에 μ˜ν•΄ κ²°μ •λœλ‹€. 이것이 λ°”λ‘œ λ ‰μ‹œμ»¬ μŠ€μ½”ν”„λ‹€.

 

 

2) ν•¨μˆ˜ 객체의 λ‚΄λΆ€ 슬둯 [[Environment]]

 

- ν•¨μˆ˜κ°€ μ •μ˜λœ ν™˜κ²½ (μœ„μΉ˜) κ³Ό ν˜ΈμΆœλ˜λŠ” ν™˜κ²½(μœ„μΉ˜) 은 λ‹€λ₯Ό 수 μžˆλ‹€.

- λ ‰μ‹œμ»¬ μŠ€μ½”ν”„κ°€ κ°€λŠ₯ν•˜λ €λ©΄ ν•¨μˆ˜λŠ” μžμ‹ μ΄ ν˜ΈμΆœλ˜λŠ” ν™˜κ²½κ³ΌλŠ” 상관없이 μžμ‹ μ΄ μ •μ˜λœ ν™˜κ²½, 즉 μƒμœ„ μŠ€μ½”ν”„ (ν•¨μˆ˜ μ •μ˜κ°€ μœ„μΉ˜ν•˜λŠ” μŠ€μ½”ν”„κ°€ λ°”λ‘œ μƒμœ„ μŠ€μ½”ν”„μž„) λ₯Ό κΈ°μ–΅ν•΄μ•Ό 함.

- ν•¨μˆ˜κ°€ μžμ‹ μ˜ λ‚΄λΆ€ 슬둯 [[Environment]] 에 μžμ‹ μ΄ μ •μ˜λœ ν™˜κ²½, 즉 μƒμœ„ μŠ€μ½”ν”„μ˜ μ°Έμ‘°λ₯Ό μ €μž₯ν•œλ‹€.

- μžμ‹ μ˜ λ‚΄λΆ€ 슬둯 [[Environment]] 에 μ €μž₯된 μƒμœ„ μŠ€μ½”ν”„μ˜ μ°Έμ‘°λŠ” ν˜„μž¬ μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ 가리킴.

 

- ν•¨μˆ˜ 객체의 λ‚΄λΆ€ 슬둯 [[Environment]] 에 μ €μž₯된 ν˜„μž¬ μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ μ°Έμ‘°κ°€ λ°”λ‘œ μƒμœ„ μŠ€μ½”ν”„λ‹€.

- λ˜ν•œ, μžμ‹ μ΄ ν˜ΈμΆœλ˜μ—ˆμ„ λ•Œ 생성될 ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ "μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°" 에 μ €μž₯될 참쑰값이닀.

- ν•¨μˆ˜ κ°μ²΄λŠ” λ‚΄λΆ€ 슬둯 [[Environment]] 에 μ €μž₯ν•œ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ μ°Έμ‘°, 즉 μƒμœ„ μŠ€μ½”ν”„λ₯Ό μžμ‹ μ΄ μ‘΄μž¬ν•˜λŠ” ν•œ κΈ°μ–΅ν•œλ‹€.

 

const x = 1;

function foo() {
    const x = 10;
    // μƒμœ„ μŠ€μ½”ν”„λŠ” ν•¨μˆ˜ μ •μ˜ ν™˜κ²½ (μœ„μΉ˜) 에 따라 결정됨.
    // ν•¨μˆ˜ 호좜 μœ„μΉ˜μ™€ μƒμœ„ μŠ€μ½”ν”„λŠ” μ•„λ¬΄λŸ° 관계가 μ—†μŒ

    bar();
}

// ν•¨μˆ˜ bar()λŠ” μžμ‹ μ˜ μƒμœ„ μŠ€μ½”ν”„, 즉 μ „μ—­ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ [[Environment]] 에 μ €μž₯ν•˜μ—¬ 기얡함.

function bar() {
    console.log(x);
}

foo(); //1
bar(); //1

ν•¨μˆ˜ 객체의 λ‚΄λΆ€ 슬둯 [[Environmen]] μ—λŠ” μƒμœ„ μŠ€μ½”ν”„κ°€ μ €μž₯λœλ‹€.

- ν•¨μˆ˜κ°€ 호좜되면 ν•¨μˆ˜ λ‚΄λΆ€λ‘œ μ½”λ“œμ˜ μ œμ–΄κΆŒμ΄ μ΄λ™ν•œλ‹€. 그리고 ν•¨μˆ˜ μ½”λ“œλ₯Ό ν‰κ°€ν•˜κΈ° μ‹œμž‘ν•œλ‹€.

 

1. ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성

2. ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½ 생성

γ€€2.1 ν•¨μˆ˜ ν™˜κ²½ λ ˆμ½”λ“œ 생성

γ€€2.2 this 바인딩

γ€€2.3 μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘° κ²°μ •

μ΄λ•Œ, ν•¨μˆ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ ꡬ성 μš”μ†ŒμΈ μ™ΈλΆ€ λ ‰μ‹œμ»¬ ν™˜κ²½μ— λŒ€ν•œ μ°Έμ‘°μ—λŠ” ν•¨μˆ˜ 객체의 λ‚΄λΆ€ 슬둯 [[Environment]] 에 μ €μž₯된 λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ μ°Έμ‘°κ°€ ν• λ‹Ήλœλ‹€.

즉, ν•¨μˆ˜ 객체의 λ‚΄λΆ€ 슬둯 [[Environment]] 에 μ €μž₯된 λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ μ°Έμ‘°λŠ” λ°”λ‘œ ν•¨μˆ˜μ˜ μƒμœ„ μŠ€μ½”ν”„λ₯Ό μ˜λ―Έν•œλ‹€.

이것이 λ°”λ‘œ ν•¨μˆ˜ μ •μ˜ μœ„μΉ˜μ— 따라 μƒμœ„ μŠ€μ½”ν”„λ₯Ό κ²°μ •ν•˜λŠ” λ ‰μ‹œμ»¬ μŠ€μ½”ν”„μ˜ μ‹€μ²΄μž„.

 

 

3) ν΄λ‘œμ €μ™€ λ ‰μ‹œμ»¬ ν™˜κ²½

 

const x = 1;

function outer() {
    const x = 10;
    const inner = function () { console.log(x); }
    return inner;
}

// outer ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ 쀑첩 ν•¨μˆ˜ inner λ₯Ό λ°˜ν™˜ν•œλ‹€.
// 그리고 outer ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒμ—μ„œ νŒλ˜μ–΄ μ œκ±°λœλ‹€.

const innerFunc = outer();
innerFunc();	//10

 

- μœ„ μ½”λ“œμ—μ„œ outerν•¨μˆ˜λŠ” inner ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜κ³  생λͺ…μ£ΌκΈ°(life cycle)λ₯Ό λ§ˆκ°ν•œλ‹€.

- 즉, outer ν•¨μˆ˜μ˜ 싀행이 μ’…λ£Œλ˜λ©΄ outer ν•¨μˆ˜μ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μŠ€νƒμ—μ„œ 제거(pop)됨. (outer ν•¨μˆ˜μ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ€ μ†Œλ©Έν•˜μ§€ μ•ŠμŒ.)

- κ·Έλ ‡κΈ° λ•Œλ¬Έμ—, inner ν•¨μˆ˜λŠ” (쀑첩 ν•¨μˆ˜) outer ν•¨μˆ˜ (μ™ΈλΆ€ ν•¨μˆ˜) 의 λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜κ³  있기 λ•Œλ¬Έμ— μ½”λ“œμ˜ μ‹€ν–‰ κ²°κ³Όμ—μ„œλŠ” μ™ΈλΆ€ ν•¨μˆ˜μΈ outer ν•¨μˆ˜μ˜ μ§€μ—­ λ³€μˆ˜ x 의 값인 10이 좜λ ₯λœλ‹€. μ΄λŸ¬ν•œ 쀑첩 ν•¨μˆ˜λ₯Ό ν΄λ‘œμ €(closure) 라고 뢀름. πŸ˜‹

 

- ν΄λ‘œμ €(closure)λŠ” 쀑첩 ν•¨μˆ˜κ°€ μƒμœ„ μŠ€μ½”ν”„μ˜ μ‹λ³„μžλ₯Ό μ°Έκ³ ν•˜κ³  있고, 쀑첩 ν•¨μˆ˜κ°€ μ™ΈλΆ€ ν•¨μˆ˜λ³΄λ‹€ 더 였래 μœ μ§€λ˜λŠ” κ²½μš°μ— ν•œμ •ν•˜λŠ” 것이 μΌλ°˜μ μž„.

 

 

4) ν΄λ‘œμ €μ˜ ν™œμš©

 

- ν΄λ‘œμ €λŠ” μƒνƒœλ₯Ό μ•ˆμ „ν•˜κ²Œ λ³€κ²½ν•˜κ³ , μœ μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

- μƒνƒœλ₯Ό μ•ˆμ „ν•˜κ²Œ 은닉 (information hiding) ν•˜κ³  νŠΉμ • ν•¨μˆ˜μ—κ²Œλ§Œ μƒνƒœ 변경을 ν—ˆμš©ν•œλ‹€.

 

// 카운트 μƒνƒœ λ³€κ²½ ν•¨μˆ˜
const increase = (function () {
    // 카운트 μƒνƒœ λ³€μˆ˜
    let num = 0;

    // ν΄λ‘œμ €
    return function () {
        return ++num;
    };
}());

console.log(increase());	//1
console.log(increase());	//2
console.log(increase());	//3

 

- μœ„ μ½”λ“œμ—μ„œλŠ” μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜κ°€ 호좜되고, μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ ν•¨μˆ˜κ°€ increase λ³€μˆ˜μ— 할당됨.

- increase λ³€μˆ˜μ— ν• λ‹Ήλœ ν•¨μˆ˜λŠ” μžμ‹ μ΄ μ •μ˜λœ μœ„μΉ˜μ— μ˜ν•΄ κ²°μ •λœ μƒμœ„ μŠ€μ½”ν”„μΈ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κΈ°μ–΅ν•˜λŠ” ν΄λ‘œμ €λ‹€.

 

- μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜λŠ” ν•œ 번만 μ‹€ν–‰λ˜λ―€λ‘œ increaseκ°€ 호좜될 λ•Œλ§ˆλ‹€ num λ³€μˆ˜κ°€ 재차 μ΄ˆκΈ°ν™”λ  일은 μ—†κ³ , λ˜ν•œ num λ³€μˆ˜λŠ” μ™ΈλΆ€μ—μ„œ 직접 μ ‘κ·Όν•  수 μ—†λŠ” μ€λ‹‰λœ private λ³€μˆ˜μ΄λ―€λ‘œ μ „μ—­ λ³€μˆ˜λ₯Ό μ‚¬μš©ν–ˆμ„ λ•Œμ™€ 같이 μ˜λ„λ˜μ§€ μ•Šμ€ 변경을 κ±±μ •ν•  ν•„μš”λ„ μ—†κΈ° λ•Œλ¬Έμ— μ•ˆμ •μ μ΄λ‹€!

 

- 이처럼 ν΄λ‘œμ €λŠ” μƒνƒœκ°€ μ˜λ„μΉ˜ μ•Šκ²Œ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ μ•ˆμ „ν•˜κ²Œ μ€λ‹‰ν•˜κ³ , νŠΉμ • ν•¨μˆ˜μ—κ²Œλ§Œ μƒνƒœ 변경을 ν—ˆμš©ν•˜μ—¬ μƒνƒœλ₯Ό μ•ˆμ „ν•˜κ²Œ λ³€κ²½ν•˜κ³ , μœ μ§€ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•¨.

 

const counter = (function () {
    // μΉ΄μš΄ν„° μƒνƒœ λ³€μˆ˜
    let num = 0;

    // ν΄λ‘œμ €μΈ λ©”μ„œλ“œλ₯Ό κ°–λŠ” 객체λ₯Ό λ°˜ν™˜
    // 객체 λ¦¬ν„°λŸ΄μ€ μŠ€μ½”ν”„λ₯Ό λ§Œλ“€μ§€ μ•ŠμŒ
    // λ”°λΌμ„œ μ•„λž˜ λ©”μ„œλ“œλ“€μ˜ μƒμœ„ μŠ€μ½”ν”„λŠ” μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μž„
    
    return {
        // num: 0, ν”„λ‘œνΌν‹°λŠ” pbulic ν•˜λ―€λ‘œ μ€λ‹‰λ˜μ§€ μ•ŠμŒ!
        increase() {
            return ++num;
        },
        decrease() {
            return num > 0 ? --num : 0;
        }
    };
}());

console.log(counter.increase());	//1
console.log(counter.increase());	//2
console.log(counter.decrease());	//1
console.log(counter.decrease());	//0

 

μœ„ μ½”λ“œμ—μ„œ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜κ°€ λ°˜ν™˜ν•˜λŠ” 객체 λ¦¬ν„°λŸ΄μ€ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ μ‹€ν–‰ λ‹¨κ³„μ—μ„œ ν‰κ°€λ˜μ–΄ 객체가 됨.

객체의 λ©”μ„œλ“œλ„ ν•¨μˆ˜ 객체둜 μƒμ„±λ˜κ³ , 객체 λ¦¬ν„°λŸ΄μ˜ μ€‘κ΄„ν˜ΈλŠ” μ½”λ“œ 블둝이 μ•„λ‹ˆλ―€λ‘œ λ³„λ„μ˜ μŠ€μ½”ν”„λ₯Ό μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€.

 

increase 와 decrease의 μƒμœ„ μŠ€μ½”ν”„λŠ” 두 개의 λ©”μ„œλ“œκ°€ ν‰κ°€λ˜λŠ” μ‹œμ μ— μ‹€ν–‰ 쀑인 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμΈ μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ΄λ‹€.

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ–Έμ œ μ–΄λ””μ„œ ν˜ΈμΆœλ˜λŠ” 상관없이 μ¦‰μ‹œ μ‹€ν–‰ ν•¨μˆ˜μ˜ μŠ€μ½”ν”„μ˜ μ‹λ³„μžλ₯Ό μ°Έμ‘°ν•  수 있음!

 

λ³€μˆ˜ 값은 λˆ„κ΅°κ°€μ— μ˜ν•΄ μ–Έμ œλ“ μ§€ 변경될 수 μžˆμ–΄ 였λ₯˜ λ°œμƒμ˜ 근본적 원인이 될 수 있음.

μ™ΈλΆ€ μƒνƒœ λ³€κ²½μ΄λ‚˜ κ°€λ³€(mutable) 데이터λ₯Ό ν”Όν•˜κ³  λΆˆλ³€μ„±(immutability) 을 μ§€ν–₯ν•˜λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ λΆ€μˆ˜ 효과λ₯Ό μ΅œλŒ€ν•œ μ–΅μ œν•˜μ—¬ 였λ₯˜λ₯Ό ν”Όν•˜κ³  ν”„λ‘œκ·Έλž¨μ˜ μ•ˆμ •μ„±μ„ 높이기 μœ„ν•΄ ν΄λ‘œμ €λŠ” 적극적으둜 μ‚¬μš©λ¨.

 

// ν•¨μˆ˜λ₯Ό 인수둜 전달받고 ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” κ³ μ°¨ν•¨μˆ˜
// 이 ν•¨μˆ˜λŠ” 카운트 μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜ counter λ₯Ό κΈ°μ–΅ν•˜λŠ” ν΄λ‘œμ €λ₯Ό λ°˜ν™˜ν•œλ‹€.
function makeCounter (predicate) {
    // μΉ΄μš΄ν„° μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜
    let counter = 0;

    // ν΄λ‘œμ €λ₯Ό λ°˜ν™˜
    return function () {
        // 인수둜 전달받은 보쑰 ν•¨μˆ˜μ— μƒνƒœ 변경을 μœ„μž„ν•œλ‹€.
        counter = predicate(counter);
        return counter;
    };
}

// λ³΄μ‘°ν•¨μˆ˜
function increase2(n) {
    return ++n;
}

// λ³΄μ‘°ν•¨μˆ˜
function decrease2(n) {
    return --n;
}

// ν•¨μˆ˜λ‘œ ν•¨μˆ˜λ₯Ό μƒμ„±ν•œλ‹€.
// makeCounter ν•¨μˆ˜λŠ” 보쑰 ν•¨μˆ˜λ₯Ό 인수둜 전달받아 ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•¨
const increaser = makeCounter(increase2);
console.log(increaser());   //1
console.log(increaser());   //2

// increaser ν•¨μˆ˜μ™€λŠ” λ³„κ°œμ˜ λ…λ¦½λœ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ°–κΈ° λ•Œλ¬Έμ— μΉ΄μš΄ν„° μƒνƒœκ°€ μ—°λ™λ˜μ§€ μ•ŠμŒ
const decreaser = makeCounter(decrease2);
console.log(decreaser());   //-1
console.log(decreaser());   //-2

 

μœ„ μ½”λ“œμ—μ„œ makeCounter ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•  λ•Œ λ°˜ν™˜λœ ν•¨μˆ˜λŠ” μžμ‹ λ§Œμ˜ λ…λ¦½λœ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ°–λŠ”λ‹Ή.

makeCounter ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ ν•¨μˆ˜λŠ” makeCounter ν•¨μˆ˜μ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ μƒμœ„ μŠ€μ½”ν”„λ‘œμ„œ κΈ°μ–΅ν•˜λŠ” ν΄λ‘œμ €λ‹€.

makeCounter ν•¨μˆ˜ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ ‰μ‹œμ»¬ ν™˜κ²½μ€ makeCounter ν•¨μˆ˜κ°€ λ°˜ν™˜ν•œ ν•¨μˆ˜μ˜ [[Environment]] λ‚΄λΆ€ μŠ¬λ‘―μ— μ˜ν•΄ 참쑰되고 있기 λ•Œλ¬Έμ— μ†Œλ©Έλ˜μ§€ μ•ŠμŒ!!!!!!!

 

μœ„ μ½”λ“œμ—μ„œλŠ” μ „μ—­ λ³€μˆ˜ increaser 와 decreaser 에 ν• λ‹Ήλœ ν•¨μˆ˜λŠ” 각각 μžμ‹ λ§Œμ˜ λ…λ¦½λœ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ°–κΈ° λ•Œλ¬Έμ— 카운트λ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜ counter λ₯Ό κ³΅μœ ν•˜μ§€ μ•Šμ•„ μΉ΄μš΄ν„°μ˜ 증감이 μ—°λ™λ˜μ§€ μ•ŠμŒ! λ”°λΌμ„œ, λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ³΅μœ ν•˜λŠ” ν΄λ‘œμ €λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜λ¬΄λ‹ˆλ‹€.

 

//λ…λ¦½λœ μΉ΄μš΄ν„°κ°€ μ•„λ‹Œ, μ—°λ™ν•˜μ—¬ 증감이 κ°€λŠ₯ν•œ μΉ΄μš΄ν„°λ₯Ό λ§Œλ“€λ €λ©΄ λ ‰μ‹œμ»¬ ν™˜κ²½μ„ κ³΅μœ ν•˜λŠ” ν΄λ‘œμ €λ₯Ό λ§Œλ“€μ–΄μ•Ό 함.

//ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” κ³ μ°¨ ν•¨μˆ˜
//이 ν•¨μˆ˜λŠ” 카운트 μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜ counter λ₯Ό κΈ°μ–΅ν•˜λŠ” ν΄λ‘œμ €λ₯Ό λ°˜ν™˜ν•œλ‹€.
const counter2 = (function () {
    //μΉ΄μš΄ν„° μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ 자유 λ³€μˆ˜
    let counter2 = 0;
    //ν•¨μˆ˜λ₯Ό 인수둜 전달받아 ν΄λ‘œμ €λ₯Ό λ°˜ν™˜
    return function (predicate) {
        //인수둜 전달받은 보쑰 ν•¨μˆ˜μ— μƒνƒœ 변경을 μœ„μž„ν•¨
        counter2 = predicate(counter2);
        return counter2;
    };
}());

//λ³΄μ‘°ν•¨μˆ˜
function increase3 (n) {
    return ++n;
}

//λ³΄μ‘°ν•¨μˆ˜
function decrease3 (n) {
    return --n;
}

//λ³΄μ‘°ν•¨μˆ˜λ₯Ό μ „λ‹¬ν•˜μ—¬ 호좜
console.log(counter2(increase3));
console.log(counter2(increase3));
console.log(counter2(decrease3));
console.log(counter2(decrease3));
//μžμœ λ³€μˆ˜λ₯Ό κ³΅μœ ν•˜κ³  있돡.

 

κ²°λ‘ .

ν΄λ‘œμ €λž€ ν•¨μˆ˜μ™€ ν•΄λ‹Ή ν•¨μˆ˜κ°€ μ„ μ–Έλœ λ ‰μ‹œμ»¬ ν™˜κ²½μ˜ μ‘°ν•©!

μ™ΈλΆ€ ν•¨μˆ˜κ°€ λ°˜ν™˜λœ 후에도 μ™ΈλΆ€ ν•¨μˆ˜μ˜ λ³€μˆ˜ λ²”μœ„ 체인에 μ ‘κ·Όν•  수 μžˆλŠ” ν•¨μˆ˜λ‹€!

μ „μ—­ λ³€μˆ˜μ˜ μ‚¬μš©μ„ μ–΅μ œν•˜κ³ , 정보λ₯Ό μ€λ‹‰ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€λŠ” 것이닀. πŸ˜†

728x90

'JavaScript πŸ“' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

null κ³Ό undefined 의 차이점  (0) 2022.12.21
이벀트 루프와 νƒœμŠ€ν¬ 큐  (0) 2022.12.18
동기/비동기  (0) 2022.12.10
ν˜Έμ΄μŠ€νŒ…(hoisting)  (0) 2022.12.09
Truthy와 Falsy  (0) 2022.11.30
Comments