closure
ν¨μμ ν¨μκ° μ μΈλ μ΄νμ (lexical) νκ²½μ μ‘°ν©
μλ°μ€ν¬λ¦½νΈλ ν¨μκ° νΈμΆλλ νκ²½κ³Ό λ³κ°λ‘, κΈ°μ‘΄μ μ μΈλμ΄ μλ νκ²½ - μ΄νμ νκ²½ - μ κΈ°μ€μΌλ‘ λ³μλ₯Ό μ‘°ννλ€.
κ°λ¨ν λ§νλ©΄ μΈλΆ ν¨μμ 컨ν
μ€νΈμ μ κ·Όν μ μλ λ΄λΆ ν¨μλ₯Ό ν΄λ‘μ λΌκ³ ν¨!
ν¨μ μ μΈλ¬ΈμΌλ‘ μ μΈν ν¨μλ μΌλ° λ³μμλ λ¬λ¦¬ λ°λ‘ μ΄κΈ°νκ° λλ€.
μΈλΆν¨μμ μ€νμ΄ μ’
λ£λ νμλ, ν΄λ‘μ ν¨μλ μΈλΆν¨μμ μ€μ½ν, μ¦, ν¨μκ° μ μΈλ μ΄νμ νκ²½μ μ κ·Όν μ μμ΅λλ€.
ν΄λ‘μ μ¬μ© μμ: ν΄λ‘μ λ₯Ό ν΅ν΄ 컀λ§(currying, ν¨μ νλκ° nκ°μ μΈμλ₯Ό λ°λ λμ nκ°μ ν¨μλ₯Ό λ§λ€μ΄ κ°κ° μΈμλ₯Ό λ°κ² νλ λ°©λ²), ν΄λ‘μ λͺ¨λ(λ³μλ₯Ό μΈλΆ ν¨μ μ€μ½ν μμͺ½μ κ°μΆμ΄, λ³μκ° ν¨μ λ°μμ λ
ΈμΆλλ κ²μ λ§λ λ°©λ²)
νΉμ§
scope ν¨μλ λκ°μ§ νΉμ§μ λ§μ‘±ν΄μΌνλ€.
ν¨μλ₯Ό 리ν΄νλ ν¨μ
const adder = function (x) {
return function (y) {
return x + y;
}
}
JavaScript
볡μ¬
리ν΄κ°μ΄ ν¨μμ ννμ΄λ€.
λ΄λΆ ν¨μμ μΈλΆ ν¨μ
리ν΄νλ ν¨μμ μν΄ μ€μ½νκ° κ΅¬λΆλλ―λ‘ λ΄λΆ ν¨μλ μΈλΆ ν¨μμ μ μΈλ λ³μμ μ κ·Όμ΄ κ°λ₯νλ€.
μΈλΆ ν¨μλ μμͺ½ μ€μ½νμμ μ μΈλ λ³μμ μ κ·Όμ΄ λΆκ°λ₯νκ³ λ΄λΆ ν¨μμμλ λ°κΉ₯ μ€μ½νμμ μ μΈλ λ³μμ μ κ·Όμ΄ κ°λ₯νλ€
closure ν¨μμ μ₯μ
λ°μ΄ν°λ₯Ό 보쑴νλ ν¨μ
μΈλΆν¨μμ μ€νμ΄ λλλλΌλ μΈλΆ ν¨μ λ΄ λ³μλ₯Ό μ¬μ©ν μ μμ
μΌλ°μ μΈ ν¨μλ ν¨μ μ€νμ΄ λλ ν ν¨μ λ΄λΆμ λ³μλ₯Ό μ¬μ©ν μ μλ€ νμ§λ§ ν΄λ‘μ ν¨μλ μΈλΆ ν¨μμ μ€ν΄μ΄ λλλλΌλ μΈλΆ ν¨μ λ΄ λ³μκ° λ©λͺ¨λ¦¬ μμ μ μ₯λλ€.
μ΄μ²λΌ νΉμ λ°μ΄ν°λ₯Ό μ€μ½ν μμ κ°λμ΄ λ μ±λ‘ κ³μ μ¬μ©ν μ μλ€
const adder = function (x) {
return function (y) {
return x + y;
}
}
const add5 = adder(5);
add5(7); // 12
add5(10); // 15
JavaScript
볡μ¬
ν΄λ‘μ ν¨μλ₯Ό μ¬μ©ν HTML λ¬Έμμ΄ μμ±κΈ° λ§λ€κΈ°
const tagMaker = tag => content => `<${tag}>${content}</${tag}>`
const divMaker = tagMaker('div');
divMaker('hello'); // '<div>hello</div>'
const anchorMaker = tagMaker('a');
anchorMaker('go'); // '<a>go</a>';
JavaScript
볡μ¬
μ 보μ μ κ·Ό μ ν
const makeCounter = () => {
let value = 0;
return {
increase: () => {
value = value + 1
},
decrease: () => {
value = value - 1
},
getValue: () => value
}
}
const counter1 = makeCounter();
counter1 // {increase: f, decrease: f, getValue: f}
JavaScript
볡μ¬
ν΄λ‘μ λ₯Ό μ΄μ©ν΄ λ΄λΆ ν¨μλ₯Ό κ°μ²΄μ λ΄μμ μ¬λ¬ κ°μ λ΄λΆ ν¨μλ₯Ό 리ν΄νλλ‘ λ§λ λ€.
μΈλΆ μ€μ½νμμ λ΄λΆ μ€μ½νμ λ³μμ μ κ·Όν μ μμΌλ―λ‘ μ°λ¦¬λ makeCounterλ₯Ό λ°κΎΈμ§ μκ³ λ΄λΆμ μ μΈλ valueμ μλ‘μ΄ κ°μ ν λΉν μ μλ€.
β μ΄κ²μ μΊ‘μν(μ 보μ μ κ·Ό μ ν) λΌκ³ νλ€.
side effectμ λ°λ₯Έ μ€λ₯λ‘λΆν° λ°μ΄ν°λ₯Ό μμ νκ² λ³΄νΈν μ μλ€.
ν΄λ‘μ λ₯Ό ν΅ν΄ λΆνμν μ μ λ³μ μ¬μ©μ μ€μ΄κ³ , μ€μ½νλ₯Ό μ΄μ©ν΄ κ°μ λ³΄λ€ μμ νκ² λ€λ£° μ μλ€.
λͺ¨λν
ν¨μ μ¬μ¬μ©μ±μ κ·Ήλννμ¬ ν¨μ νλλ₯Ό μμ ν λ
립μ μΈ λΆν ννλ‘ λΆλ¦¬
const counter1 = makeCounter()
const counter2 = makeCouter()
JavaScript
볡μ¬
λ counterλ λ
립μ μΌλ‘ λμκ°λ€.
ν΄λ‘μ λ λͺ¨λνμ μ 리νλ€.
closure ν¨μμ λ¨μ
μλ°μ€ν¬λ¦½νΈλ κ°λΉμ§ 컬λ μ
μ ν΅ν΄ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό ν©λλ€. κ°μ²΄κ° μ°Έμ‘° λμμ΄ μλ λ, κ°λΉμ§ 컬λ μ
μ μν΄ μλμΌλ‘ λ©λͺ¨λ¦¬ ν λΉμ΄ ν΄μ λ©λλ€. μΌλ° ν¨μμλ€λ©΄ ν¨μ μ€ν μ’
λ£ ν κ°λΉμ§ 컬λ μ
(μ°Έκ³ μλ£: MDN 'μλ°μ€ν¬λ¦½νΈμ λ©λͺ¨λ¦¬ κ΄λ¦¬') λμμ΄ λμμ κ°μ²΄κ°, ν΄λ‘μ ν¨ν΄μμλ λ©λͺ¨λ¦¬ μμ λ¨μ μκ² λ©λλ€. μΈλΆ ν¨μ μ€μ½νκ° λ΄λΆν¨μμ μν΄ μΈμ λ μ§ μ°Έμ‘°λ μ μκΈ° λλ¬Έμ
λλ€. λ°λΌμ ν΄λ‘μ λ₯Ό λ¨λ°ν κ²½μ° νΌν¬λ¨Όμ€ μ νκ° λ°μν μλ μμ΅λλ€.
β’
μ μ: ν¨μμ ν¨μκ° μ μΈλ μ΄νμ νκ²½(lexical environment)μ μ‘°ν©
* νΉμ§: λ΄λΆ ν¨μκ° μΈλΆ ν¨μ μμ μ μΈλ λ³μμ μ κ·Όν μ μλ€. λ΄λΆ ν¨μλ₯Ό ν΄λ‘μ ν¨μλΌκ³ λΆλ₯΄κΈ°λ νλ€.
* μμ©: namespacing, privacy, function factory, partially applied functions, ...
*
β’
μ΄λ₯Ό νμ©νμ¬ κΈ°μ‘΄ ν¨μκ° μ¬λ¬ λ² μ€νλλ©΄ κ²°κ³Όκ° λ³λλλ ν¨μλ₯Ό, ν λ² λ¦¬ν΄λ κ°λ§ 리ν΄νκ² νλ ν¨μ(_.once)μ
* κΈ°μ‘΄ ν¨μκ° μ¦μ μ€ν λλ ν¨μλ₯Ό, μΌμ μκ° μ΄νμ μ€νλκ² νλ ν¨μ(_.delay)λ‘ λ§λ€μ΄λ΄
μλ€.
*
* μ΄λ μΌλ°μ μΈ νλ‘κ·Έλλ° λμμΈ ν¨ν΄ μ€ λ°μ½λ μ΄ν°(λλ wrapper) ν¨ν΄κ³Ό μ μ¬ν©λλ€.
* λ°μ½λ μ΄ν° ν¨ν΄μ κ°μ²΄λ₯Ό κΎΈλ―Έκ±°λ(decorate) κ°μΈμ(wrap) κΈ°μ‘΄ κ°μ²΄μ κΈ°λ₯ λλ νλμ μΆκ°ν©λλ€.
* μμΈν λ΄μ©μ μλ λ§ν¬λ₯Ό νμΈνμκΈ° λ°λλλ€. Advancedν λ΄μ©μ΄λ―λ‘ μ§κΈ λΉμ₯ μ½μ§ μμΌμ
λ λ©λλ€.
* μ΄λ‘ : https://refactoring.guru/design-patterns/decorator
* ꡬν: https://www.dofactory.com/javascript/design-patterns/decorator