6.1 ํด๋ก์ ๊ฐ๋
ํด๋ก์ ๋ JavaScript์์ ๊ฐ์ฅ ๊ฐ๋ ฅํ๊ณ ์ค์ํ ๊ฐ๋ ์ค ํ๋์ผ. ํด๋ก์ ๋ฅผ ํตํด ํจ์๋ ์คํ ํ์๋ ์์ ์ ๋ ์์ปฌ ํ๊ฒฝ์ ๊ธฐ์ตํ ์ ์๊ฒ ํด์ค. ์ด๋ฒ ๊ฐ์์์๋ ํด๋ก์ ์ ๊ฐ๋ , ํน์ง ๋ฐ ๋ค์ํ ์ฌ์ฉ ์์ ๋ฅผ ์ดํด๋ณผ ๊ฑฐ์ผ.
JavaScript์์ ํด๋ก์ (closure)๋ ํจ์์ ๊ทธ ํจ์๊ฐ ์ ์ธ๋ ๋ ์์ปฌ ํ๊ฒฝ์ ์กฐํฉ์ด์ผ. ํด๋ก์ ๋ ํจ์๊ฐ ์ธ๋ถ ํจ์๊ฐ ์คํ๋ ํ์๋ ์ธ๋ถ ์ค์ฝํ์ ๋ณ์์ ๋ค๋ฅธ ํจ์์ ์ ๊ทผํ ์ ์๊ฒ ํด์ค.
ํด๋ก์ ์ ์ฃผ์ ์์ฑ:
- ๋ ์์ปฌ ํ๊ฒฝ: ํจ์๊ฐ ์ ์ธ๋ ์ปจํ ์คํธ๋ก, ์ ์ธ ์์ ์ ์ ๊ทผ ๊ฐ๋ฅํ ๋ชจ๋ ๋ณ์๋ฅผ ํฌํจํด.
- ์ปจํ ์คํธ ์ ์ง: ํด๋ก์ ๋ฅผ ๊ฐ์ง ํจ์๋ ์ธ๋ถ ํจ์๊ฐ ์คํ ์๋ฃ๋ ํ์๋ ์ธ๋ถ ์ค์ฝํ์ ๋ณ์์ ์ ๊ทผํ ์ ์์ด.
6.2 ํด๋ก์ ์ฌ์ฉ ์์
์์ 1: ๊ฐ๋จํ ํด๋ก์
์ด ์์ ์์ innerFunction()
์ outerVariable
์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ outerFunction()
์ด ์คํ ์๋ฃ๋ ํ์๋ ๊ณ์ ์ ๊ทผ ๊ฐ๋ฅํด.
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // ์ถ๋ ฅ: I am from the outer function
์์ 2: ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ์นด์ดํฐ
์ด ์์ ์์๋ ์นด์ดํฐ ํจ์๊ฐ count
๋ณ์์ ๊ฐ์ ์ ์ฅํ๊ณ , ํธ์ถ๋ ๋๋ง๋ค 1์ฉ ์ฆ๊ฐ์์ผ.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // ์ถ๋ ฅ: 1
console.log(counter()); // ์ถ๋ ฅ: 2
console.log(counter()); // ์ถ๋ ฅ: 3
์์ 3: ๋ฃจํ์์ ํด๋ก์
ํด๋ก์ ๋ ๋ฃจํ์์ ๋ณ์ ๊ฐ์ ์ ์ฅํ๋ ๋ฐ ์์ฃผ ์ฌ์ฉ๋ผ.
์ด ์์ ์์๋ ๋ฐฐ์ด arr
๋ด๋ถ์ ๊ฐ ํจ์๊ฐ i
๋ณ์๋ฅผ ์์ฑ ์์ ์ ๊ฐ์ผ๋ก "๊ธฐ์ต"ํด, let
์ ๋ธ๋ก ์ค์ฝํ ๋๋ถ์:
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // ์ถ๋ ฅ: 0
closures[1](); // ์ถ๋ ฅ: 1
closures[2](); // ์ถ๋ ฅ: 2
6.3 ํด๋ก์ ์ ๋ณต์กํ ์ฌ์ฉ ์๋๋ฆฌ์ค
์์ 1: ํจ์์ ๋ถ๋ถ์ ์ ์ฉ (partial application)
ํด๋ก์ ๋ ์ผ๋ถ ์ธ์๋ฅผ ๊ณ ์ ๋ ์ํ๋ก ์ ์งํ์ฌ ๋ถ๋ถ์ ์ผ๋ก ์ ์ฉ๋ ํจ์๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค.
์ด ์์ ์์๋ multiply()
ํจ์๊ฐ ๊ณ ์ ๋ ์ธ์ a
์ b
๋ฅผ ๊ณฑํ๋ ํจ์๋ฅผ ๋ฐํํด.
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // ์ถ๋ ฅ: 10
console.log(double(10)); // ์ถ๋ ฅ: 20
์์ 2: ๋ฐ์ดํฐ ์จ๊ธฐ๊ธฐ (data hiding)
ํด๋ก์ ๋ ๋น๊ณต๊ฐ ๋ณ์์ ๋ฉ์๋๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ด.
์ด ์์ ์์๋ ๋ณ์ _name
๊ณผ _age
๊ฐ ๋น๊ณต๊ฐ์ด๋ฉฐ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํตํด์๋ง ์ ๊ทผ ๊ฐ๋ฅํด:
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('John', 30);
console.log(person.getName()); // ์ถ๋ ฅ: John
person.setName('Jane');
console.log(person.getName()); // ์ถ๋ ฅ: Jane
console.log(person.getAge()); // ์ถ๋ ฅ: 30
์์ 3: ๋ฉ๋ชจ์ด์ ์ด์
๋ฉ๋ชจ์ด์ ์ด์ ์ ๋์ผํ ์ ๋ ฅ๊ฐ์ ๋ํ ๋ฐ๋ณต ๊ณ์ฐ์ ํผํ๊ธฐ ์ํด ํจ์์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ์ต์ ํ ๊ธฐ๋ฒ์ด์ผ.
์ด ์์ ์์๋ memoize()
ํจ์๊ฐ ํด๋ก์ ๋ฅผ ์ฌ์ฉํ์ฌ fn()
ํจ์์ ๊ณ์ฐ๋ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํด:
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Computing...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // ์ถ๋ ฅ: Computing... 10
console.log(memoizedFunction(5)); // ์ถ๋ ฅ: 10 (์บ์์์ ๊ฒฐ๊ณผ ๊ฐ์ ธ์ด)
GO TO FULL VERSION