반응형
const x=1;
function outer(){
const x=10;
const inner=function(){
console.log(x);
}
return inner;
}
const innerFunc=outer();
innerFunc(); // 10
외부함수보다 중첩함수가 더 오래 유지되는 경우 중첩함수는 이미 생명주기가 종료된 외부함수의 변수를 참조할 수 있음
이런 중첩함수를 클로저라 부름
상위 함수의 실행컨텍스트는 사라지지만, 렉시컬 환경은 inner함수에 의해 참조되어 사라지지않기때문에 가능함
참조되고 있는 메모리를 가비지 컬렉팅 하지 않음
상위 함수의 렉시컬 환경을 참조하는 경우만 클로저이다.
상위 함수의 렉시컬 환경을 참조 하지않으면 상위 함수의 렉시컬 환경은 가비지컬렉팅 대상이됨
일부만 참조하는경우
일부만 참조하는 경우 최적화를 통해 해당 식별자만을 기억한다.
클로저에 의해 참조되는 상위스코프의 변수를 자유변수라고 부른다.
클로저의 활용
상태 은닉을 위해 사용가능함
const increase=(function(){
let num=0;
return function(){
return ++num;
}
}());
console.log(increse());
상태가 의도치 않게 변경되지 않게 하고, 특정 함수에 의해서만 상태 변경이 허용되므로 상태를 안전하게 변경하고 유지할 수 있게됨
생성자 함수로 활용
const Counter=(function(){
let num=0;
function Counter(){
}
Counter.prototype.increase=function(){
return ++num;
}
Counter.prototype.decrease=function(){
return --num;
}
return Counter
}());
const counter=new Counter();
counter.increase(); //1
자주 발생하는 실수
for문은 회문마다 새로운 렉시컬 환경을 만든다.
var funcs=[];
for (var i=0; i<3; i++){
func[i]=function(){return i;}
}
for (var j=0; j<3; j++){
func[j](); //3 3 3
}
var가 전역으로 작동하여 회문마다 새로운 렉시컬 환경을 만들지 못해서 발생함
해결방법
- let키워드 사용
var funcs=[];
for (let i=0; i<3; i++){
func[i]=function(){return i;}
}
for (var j=0; j<3; j++){
func[j](); //1 2 3
}
- 새로운 함수 영역 생성
var funcs=[];
for (var i=0; i<3; i++){
func[i]=(function(id){
return function(){
return id;
};
}(i));
}
for (var j=0; j<3; j++){
func[j](); //1 2 3
}
반응형