김정호 2021. 8. 18. 19:00

 

 

클로저(closure)

내부함수가 외부함수의 맥락(context)에 접근할 수 있는 것을 가르킨다.
클로저는 자바스크립트를 이용한 고난이도의 테크닉을 구사하는데 필수적인 개념으로 활용된다.

내부함수

자바스크립트는 함수 안에서 또 다른 함수를 선언할 수 있다.

예제

function outter(){
    function inner(){
        var title = 'coding everybody'; 
        alert(title);
    }
    inner();
}
outter();

위의 예제의 결과는 경고창에 coding everybody가 출력될 것이다.
함수 inner를 내부함수라고 한다.

예제 2

function outter(){
    var title = 'coding everybody';  
    function inner(){        
        alert(title);
    }
    inner();
}
outter();

위의 예제 결과는 coding everbody이다.
내부함수는 외부함수의 지역변수에 접근할 수 있다.

클로저와 내부함수와의 관계

클로저(closure)는 내부함수와 밀접한 관계를 가지고 있는 주제다.
내부함수는 외부함수의 지역변수에 접근 할 수 있는데 외부함수의 실행이 끝나서 외부함수가 소멸된 이후에도 내부함수가 외부함수의 변수에 접근 할 수 있다.
이러한 메커니즘을 클로저라고 한다.

예제

위의 예제의 결과는 경고창으로 coding everybody가 출력된다.

function outter(){
    var title = 'coding everybody';  
    return function(){        
        alert(title);
    }
}
inner = outter();
inner();

실행 순서

  • 7행에서 함수 outter를 호출하고 있다. 그 결과가 변수 inner에 담긴다.
  • 그 결과는 이름이 없는 함수다.
  • 실행이 8행으로 넘어오면 outter 함수는 실행이 끝났기 때문에 이 함수의 지역변수는 소멸되는 것이 자연스럽다.
    하지만 8행에서 함수 inner를 실행했을 때 coding everybody가 출력된 것은 외부함수의 지역변수 title이 소멸되지 않았다는 것을 의미한다

클로저란 내부함수가 외부함수의 지역변수에 접근 할 수 있고, 외부함수는 외부함수의 지역변수를 사용하는 내부함수가 소멸될 때까지 소멸되지 않는 특성을 의미한다.

예제

function factory_movie(title){
    return {
        get_title : function (){
            return title;
        },
        set_title : function(_title){
            title = _title
        }
    }
}
ghost = factory_movie('Ghost in the shell');
matrix = factory_movie('Matrix');
 
alert(ghost.get_title());
alert(matrix.get_title());
 
ghost.set_title('공각기동대');
 
alert(ghost.get_title());
alert(matrix.get_title());

위의 예제의 실행 결과는 Ghost in the shell -> Matrix -> 공각기동대 -> Matrix이다.

클로저는 객체의 메소드에서도 사용할 수 있다.
외부함수 안에서 만들어진 내부함수나 메소드는 외부함수의 지역변수를 공유한다.

자주 언급되는 예제

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(){
        return i;
    }
}
for(var index in arr) {
    console.log(arr[index]());
}

함수가 함수 외부의 컨텍스트에 접근할 수 있을 것으로 기대하겠지만 위의 결과는 아래와 같다.

5
5
5
5
5

코드를 변경해야 한다.

정확한 예제

var arr = []
for(var i = 0; i < 5; i++){
    arr[i] = function(id) {
        return function(){
            return id;
        }
    }(i);
}
for(var index in arr) {
    console.log(arr[index]());
}

결과는 아래와 같다.

0
1
2
3
4