티스토리 뷰
Lexical scope (static scope)
function makeFunc() {
var name = "Hello";
function displayName() {
console.log(name);
}
displayName();
}
makeFunc();
위의 코드는 자연스럽게 "Hello"가 출력됨을 예상할 수 있다. Javascript는 lexical scope(선언된 위치를 기준(compile time)으로 scope를 정함, 상대되는 개념으로 호출된 시점(run time)을 기준으로 scope를 정하는 dynamic scope가 있다.)를 사용하여 내부 함수에서 외부함수의 변수에 접근할 수 있기 때문이다.
Closure
function makeFunc() {
var name = "Hello";
function displayName() {
console.log(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
하지만 위와 같은 코드는 직관적으로 작동하는지 판단하기 어렵다. 몇몇 프로그래밍 언어에서는 함수 안의 지역변수는 그 함수가 처리되는 동안에만 존재하기 때문이다. displayName()을 return하고 나면 name에 더이상 접근할 수 없을 것으로 생각하는 것이 일반적이다.
그러나 Javascript의 경우에는 다르다. return 하는 함수가 closure를 형성하기 때문이다. 클로저는 함수와 함수의 lexical scope 환경의 조합이다. 이 환경은 클로저가 생성된 시점의 lexical scope에 있는 모든 변수로 구성된다. 즉, 클로저란 외부 함수의 호출(실행) 여부와 상관 없이 변수, 함수 등에 접근할 수 있는 함수이다. 따라서 위의 예에서 myFunc는 클로저이고 makeFunc()의 내부가 아니더라도 lexical scope에 있는 name에 접근할 수 있는 것이다.
Closure example
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* 2 */
counter1.decrement();
alert(counter1.value()); /* 1 */
alert(counter2.value()); /* 0 */
클로저를 사용하면 private 변수 및 함수를 구현할 수 있다.
(return에서 각 key에 해당하는 function() 이 선언될 때 closure(함수의 [[scopes]] property)가 형성되고 이는 makeCounter function의 execution context의 scope chain이 된다.)
'JavaScript' 카테고리의 다른 글
| Execution context, scope chain (0) | 2022.08.01 |
|---|---|
| keys, getOwnPropertyNames, for...in (0) | 2022.08.01 |
| this binding (0) | 2021.11.09 |
| prototype vs __proto__ (0) | 2021.10.06 |
| ECMA? (0) | 2021.07.12 |
