function init() {
var name = 'Mozilla'; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert(name); // uses variable declared in the parent function
}
displayName();
}
init();
displayName() 부모 함수 init()에서 선언된 변수 name에 접근,
자신만의 name변수를 가지고 있었다면, name대신 this.name을 사용했을 것이다.
displayName() 함수 내의 alert()문은 부모 함수에서 정의한 변수 name의 값을 성공적으로 출력. 이 예시를 통해 함수가 중첩된 상황에서 파서가 어떻게 변수를 처리하는지 알 수 있다.
-> 어휘적 범위 지정(lexical scoping)의 한 예. 여기서 "lexical"이란, 어휘적 범위 지정(lexical scoping) 과정에서 변수가 어디에서 사용 가능한지 알기 위해 그 변수가 소스코드 내 어디에서 선언되었는지 고려한다는 것
"함수를 리턴하는 함수“
"내부 함수는 외부 함수에 선언된 변수에 접근 가능"
리턴하는 함수에 의해 스코프(변수의 접근 범위)가 구분 -> 스코프를 이용해서, 변수의 접근 범위를 닫음(closure; 폐쇄)/ 변수 선언된 곳이 중요
"데이터를 보존하는 함수"
클로저는 외부 함수의 실행이 끝나더라도, 외부 함수 내 변수가 메모리 상에 저장된다. (어휘적 환경을 메모리에 저장하기 때문에 가능)
특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게 해준다.
ex) 클로저 모듈 패턴 : 정보의 접근 제한(캡슐화)
'value'는 직접 수정이 불가능. 대신, 리턴하는 객체가 제공하는 메소드를 통해 'value' 값을 간접적으로 조작할 수 있다.
전역 변수가 좋지 않은 이유: 다른 함수 혹은 로직 등에 의해 의도되지 않은 변경을 초래(side effect)
클로저를 통해 불필요한 전역 변수 사용을 줄이고, 스코프를 이용해 값을 보다 안전하게 다룰 수 있다
모듈화 : 함수 재사용성을 극대화하여, 함수 하나를 완전히 독립적인 부품 형태로 분리
클로저를 통해 데이터와 메소드를 같이 묶어서 다룰 수 있다. 즉, 클로저는 모듈화에 유리.
Practical closures
Emulating private methods with closures
Closure Scope Chain