클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다. (MDN 정의)
클로저는 자바스크립트의 고유 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 특성이다. 위의 정의에서 "함수가 선언된 렉시컬 환경"은 어떤 것을 의미할까?
const x = 1;
function foo() {
const x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
위의 코드를 살펴보면,
const x = 1;
// ①
function outer() {
const x = 10;
const inner = function () { console.log(x); }; // ②
return inner;
}
const innerFunc = outer(); // ③
innerFunc(); // 10
위의 코드를 살펴보면,
MDN에서 정의한 클로저 개념의 "함수가 선언된 렉시컬 환경"이란 함수가 정의된 위치의 스코프, 즉 상위 스코프를 의미하는 실행 컨텍스트의 렉시컬 환경을 말한다.
const counter = (function () {
// 카운트 상태 변수
let num = 0;
return {
// num: 0, // 프로퍼티는 pulbic하므로 은닉 불가
increase() {
return ++num;
},
decrease() {
return --num;
}
};
}());
console.log(counter.increase()); // 1
console.log(counter.increase()); // 2
console.log(counter.decrease()); // 1
console.log(counter.decrease()); // 0
위의 코드를 살펴보면,
// 함수를 반환하는 고차 함수
const counter = (function () {
let counter = 0;
// 클로저 반환
return function(aux) {
// 인수로 전달받은 보조 함수에 상태 변경 위임
counter = aux(counter);
return counter;
};
}());
// 보조 함수
function increase(n) {
return ++n;
}
function decrease(n) {
return --n;
}
// 보조 함수를 전달하여 호출
console.log(counter(increase)); // 1
console.log(counter(increase)); // 2
console.log(counter(decrease)); // 1
console.log(counter(decrease)); // 0
위의 코드를 살펴보면,
const Person = (function () {
let _age = 0; // private
// 생성자 함수
function Person(name, age) {
this.name = name; // public
_age = age;
}
// 프로토타입 메서드
Person.prototype.sayHi = function () {
console.log(`Hi! My name is ${this.name}. I am ${_age}.`);
};
// 생성자 함수 반환
return Person;
}());
const me = new Person('Lee', 20);
me.sayHi(); // Hi! My name is Lee. I am 20.
console.log(me.name); // Lee
console.log(me._age); // undefined
const you = new Person('Kim', 30);
you.sayHi(); // Hi! My name is Kim. I am 30.
me.sayHi(); // Hi! My name is Lee. I am 30.
위의 코드를 살펴보면,
출처 : 모던 자바스크립트 Deep Dive