ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [javascript] 02 - 클로저 ( Closure )
    javascript 2020. 11. 7. 01:55

    한 3~4년전 자바스크립트에 관한 서적을 통해 처음 클로저를 접하였을 때 이해가 잘되지 않았습니다. 

    왜 이 상황을 보고 클로저라고 말을 하는 건지... 

     

    클로저에 관하여 자세히 포스팅된 글들을 보았습니다.
    클로저를 사용하는 이유, 특징, 스코프와의 관계, 렉시컬 스코프, 프라이빗 함수/변수, 스코프 체인... 
    클로저 하는 알기위하여 구글 검색을 했지만 위와 같은 생소한(?) 말들로 분명 글인데 글을 이해하지 못하는 문맹인이 되어있었습니다.🙈

     

    이번 포스팅은 클로저에 대하여 모든 것을 하나하나 뜯어보는 것보다 
    처음 클로저를 접한 사람에게 조금이나마 쉽게 다가갈 수 있도록 이해시키는 것을 중점으로 내용을 적겠습니다.

     

    글을 보기전 한가지만 주의하면서 봐주시길 바랍니다.
    포스팅에서 작성한 코드들의 '결과'를 생각하지말고 어떻게 값을 가져오는지 '과정'을 생각하시면서 읽으시길 바랍니다.

    실행결과는 어떤 값이 나올까?

    다음 결과는 어떻게 나올지 예상해봅시다.

    function outerFunc(){
        var fruit = 'banana';
    
        function innerFunc(){
            console.log("과일의 이름은 : %s",fruit);
        }
    
        return innerFunc;
    }
    var closureFunc = outerFunc();
    closureFunc();

     

    혹시 결과가 '과일의 이름은 : banana' 라고 생각하셨나요? 
    아니면 '과일의 이름은 : undefined' 라고 생각하셨나요? 

     

    전 강의(자바스크립트의 특징)에서 스코프에 대한 내용을 짧게 설명하였습니다.

    스코프는 변수를 사용할 수 있는 범위입니다. 

    (2020/11/03 - [javascript] - [javascript] 01 - 자바스크립트의 특징)

    함수의 구조 (위 코드 참조 )

    함수의 구조를 보면 
    outerFunc()함수 안에 fruit이라는 변수와 innerFunc()라는 함수가 있고, 
    innerFunc를 리턴하였습니다. 
    그리고 closureFunc라는 변수를 선언하고 호출하였습니다. 

     

    innerFunc()

    - innerFunc 함수에서는 fruit변수를 콘솔에서 호출하고 있습니다. 

    - 만약 해당하는 변수가 해당 함수 안에 없다면, 상위 함수에서 찾게되고 상위 함수에서도 없다면 전역변수에서 찾게 됩니다. ( 스코프 체인 )
    ==> fruit변수는 innerFunc()함수 안에 없기 때문에 상위 함수인 outerFunc()에서 찾게 됩니다.  
          상위 함수인 outerFunc()에서 fruit변수를 찾았기 때문에 fruit 변수를 가져옵니다. 

     

    한 가지 놓치고 간 자바스크립트 함수의 특징이 있습니다. 

    1. 함수가 종료되면 지역변수는 삭제된다는 잊어서는 안 될 중요한 특징입니다.
    2. 함수의 실행방법은 함수명(); 형태이고 return을 하게되면 함수가 종료된다.


     

    즉,

    var closureFunc = outerFunc(); 이 부분에서 함수가 실행되고 종료가 된 상태입니다.

    var closureFunc = outerFunc(); // 이 부분에서 함수가 실행되고 종료가 된 상태입니다. ( innerFunc함수만 반환한다.)
    closureFunc(); // closureFunc()을 실행하게되면 innerFunc함수를 실행하게된다.

    innerFunc()에서는 outerFunc()의 fruit변수를 호출하고싶어했는데
    closureFunc();를 실행 한 시점에서는 outerFunc()는 없고 innerFunc()만 있기 때문에 무언가 이상합니다. 
    에러가 나도 이상해보이지 않습니다. 
    위에서 말한 '자바스크립트 함수의 특징'을 토대로 예상해보면 분명 outerFunc()의 fruit값을 가져오지 못합니다. 
    ( outerFunc()는 함수가 종료된 시점에서 없어졌으니까!!

      outerFunc함수가 종료된 시점 : var closureFunc = outerFunc(); ) 

     


    해당 코드를 실행하게되면 undefined가 아닌 outerFunc()의 fruit값 인 'banana'를 가져옵니다. 
    '이것이 바로 클로저 (Closure) ' 입니다.

     

    클로저의 가장 큰 특징이 여기서 알 수 있습니다.
     - 자신을 포함한 상위 함수의 변수,인자들을 상위 함수가 종료된 후에도 사용할 수 있다. 

     

     

    코드 구조를 다시한번 파악해봅시다. 

    // 클로저는 자신(자기함수)을 포함한 상위 함수의 변수,인자들을 상위 함수가 종료된 후에도 사용할 수 있다. 
    // 자기함수or상위함수란 말은 없습니다. 이해를 돕기위하여 적었습니다.
    
    function outerFunc(){ // 상위함수(외부함수)
        var fruit = 'banana';
    
        function innerFunc(){ // 자기함수(내부함수) 
            console.log("과일의 이름은 : %s",fruit);
        }
    
        return innerFunc;
    }
    var closureFunc = outerFunc(); // ==> innerFunc;
    closureFunc();
    // outerFunc함수 내부에 있는 innerFunc함수를 실행하며
    // innerFunc의 상위함수인 outerFunc의 변수(fruit)가 살아있다.== (Closure)

     

     

    클로저 함수에 대해서 조금이나마 이해가 되셨으면 좋겠습니다.
    끝으로 이해가 되셨는지 다음코드의 결과를 예측하고 실행해보세요.

     

    function closureExam() {
        var message = "Hello";
        var count =1;
    
        return function () {
            var message = "bye";
            console.log(message);
            console.log(count);
            count++;
        };
    
    }
    var hello = closureExam();
    hello();
    hello();
    hello();
    hello();

     

     

    감사합니다.

     

    "끝까지 해보기 전까지는 늘 불가능해 보입니다."

    It always seems impossible until it's done

    넬슨 만델라 / nelson mandela

     

     

Designed by Tistory.