클로저 맛보기
함수가 만들어질 때의 바깥 변수를 계속 참조하는 것을 봅니다.
함수가 바깥 변수를 계속 참조합니다
앞 단원에서 함수 안에서 만든 것은 함수가 끝나면 사라진다고 했습니다. 그런데 함수가 함수를 돌려주면 이야기가 달라집니다.
돌려받은 함수가 바깥 변수를 아직 참조하고 있으면, 바깥 함수가 끝났어도 그 변수는 남습니다. 이것을 클로저(closure) 라고 합니다.
카운터 만들기
function makeCounter() { let count = 0; return function () { count++; return count; }; } const counter = makeCounter(); console.log(counter()); console.log(counter()); console.log(counter());
makeCounter() 는 이미 끝났는데
count 가 남아 값이 쌓입니다. 돌려준 함수가 그것을
아직 참조하고 있기 때문입니다.
부를 때마다 따로 생깁니다
makeCounter() 를 두 번 부르면
count 도 둘이 생깁니다. 서로 영향을 주지 않습니다.
function makeCounter() { let count = 0; return () => ++count; } const a = makeCounter(); const b = makeCounter(); console.log(a(), a(), a()); console.log(b());
++count 는 1 늘린 뒤의 값을 냅니다.
count++ 는 늘리기 전의 값을 내므로 여기서는
맞지 않습니다.
밖에서 손댈 수 없습니다
count 는 함수 안에 있어 밖에서 읽거나 바꿀 수
없습니다. 정해 둔 방법으로만 다루게 만들 때 이 성질을 사용합니다.
function makeAccount(start) { let balance = start; return { deposit: amount => balance += amount, check: () => balance }; } const account = makeAccount(1000); account.deposit(500); console.log(account.check()); console.log(account.balance);
마지막 줄이 undefined 입니다.
balance 는 밖에 없습니다. 중괄호로 여러 함수를 묶어
돌려주는 방법은 3.6 에서 다시 다룹니다.
정해 둔 값을 기억하는 함수
자주 사용하는 모양입니다. 값 하나를 미리 정해 둔 함수를 만들어 냅니다.
function makeMultiplier(times) { return n => n * times; } const double = makeMultiplier(2); const triple = makeMultiplier(3); console.log(double(10)); console.log(triple(10));
처음에 자주 걸리는 것
return counter() 는 함수를 실행한 결과를
돌려줍니다. 함수 자체를 돌려주려면 괄호 없이
return counter 입니다(2.1).
makeCounter()() 처럼 매번 새로 만들면 값이 쌓이지
않습니다. 만든 함수를 변수에 담아 두고 그것을 여러 번 불러야 합니다.
console.log(makeCounter()()); // 늘 1 입니다
바깥 함수가 끝나도 참조하는 함수가 살아 있으면 값은 남습니다. 반대로 그 함수를 더 이상 아무도 참조하지 않으면 값도 함께 정리됩니다.
직접 해보기
시작 값을 받아 부를 때마다 1씩 줄어드는 함수를 돌려주는
makeCountdown 을 만드세요.
처음 부를 때만 "실행했습니다" 를 돌려주고, 그
뒤로는 "이미 실행했습니다" 를 돌려주는 함수를
만드세요.
이 단원의 정리
- 함수가 함수를 돌려주면, 돌려받은 함수가 바깥 변수를 계속 참조합니다.
- 바깥 함수가 끝나도 그 변수는 남습니다.
- 만드는 함수를 여러 번 부르면 변수도 그만큼 따로 생깁니다.
- 그 변수는 밖에서 읽거나 바꿀 수 없습니다.
- 값을 미리 정해 둔 함수를 만들어 내는 데 자주 사용합니다.