면접 준비를 하며 javascript 기본개념을 정리해보려 한다. 그 중 가장 이해가 안되던 클로져에 대해 정리해본다.
closure에 대해 이해하기 위해선 lexical scope를 이해해야 한다. scope가 변수에 접근할 수 있는 범위라면 lexical scope는 무엇일까?
var x = 1;
function a() {
var x = 2;
b();
}
function b() {
console.log(x);
}
a(); // 1
b(); // 1
위에 코드를 보면 함수 a, b 둘 다 1을 출력하는 것을 볼 수 있다. 함수 a에서 x가 2로 할당되었는데 함수 a를 실행시켰을 때 2가 아닌 1이 출력되는 것을 볼 수 있다.
그 이유는 함수 b가 함수 a 안에서 호출되면서 지역변수 x에 접근하는 것이 아니라 함수 b가 선언되면서 전역변수 x에 접근하기 때문이다.
var num = 100;
function outter() {
var num = 1;
function inner() {
console.log(num)
}
inner();
}
outter(); // 1
위에 코드처럼 함수 inner가 함수 outter 안에서 선언되었으면 전역변수 num에 접근하는게 아니라 outter의 지역변수인 num에 접근하게된다.
이렇게 함수가 호출될 때가 아니라 함수가 선언될 때 scope가 정해지는 것을 Lexical scope라고 한다.
lexical scope를 알아보았으니 이제 closure에 대해 알아보자
function outter() {
let num = 100;
return function inner() {
console.log(num)
}
}
let closure = outter();
closure(); // 100
outter 함수 안의 num에 직접적으로 접근할 수는 없지만 closure에 outter 함수의 반환값인 inner 함수를 할당하여 closure를 실행하면 outter 안의 지역변수인 num에 접근할 수 있다. 이렇게 외부함수 밖에서 내부함수가 호출되더라도 외부함수의 지역변수에 접근할 수 있는 함수를 Closure라고 부른다
Closure를 활용하여 class의 private을 따라할 수 있다.
let counter = (function() {
let num = 0;
function add(x) {
num += x;
}
return {
increament: function() {
add(1);
},
decreament: function() {
add(-1);
},
value: function() {
return num;
}
};
})();
console.log(num); // error
console.log(counter.value()); // 0
counter.increament();
counter.increament();
counter.increament();
console.log(counter.value()); // 3
counter.decreament();
console.log(counter.value()); // 2
위 코드에서 우리는 num과 add에 직접 접근할 수 없지만 closure인 increament, decreament, value를 통해 접근할 수 있다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
https://poiemaweb.com/js-closure