ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 클로저
    Web/JavaScript 2020. 2. 2. 14:25

     

     

    비공개 변수를 가질 수 있는 환경에 있는 함수를 클로저라고 부른다.

    비공개 변수는 클로저 함수 내부에서 생성된 변수도 아니고, 매개변수도 아닌 변수를 의미하는데, 

    즉 클로저의 상위 컨텍스트에서 생성된 변수를 의미한다. 이를 구조화하면 다음처럼 된다.

    함수() {
        생성된 변수 // 비공개 변수
        return 함수 or 함수를 담은 객체
    }

    위의 구조를 따르면서 예시를 만들어보자.

    var self = function (){
        var name = "catnap";
        var age = 24;
        var height = 176;
        var girlfriend = false;
        return {
            introduce: function(){
                    console.log("my name is " + name);
                    console.log("my age is " + age);
                    console.log("my height is " + height);
                    if(girlfriend) console.log("I have girlfriend");
            },
            meeting : function(){
                    girlfriend = true;
            }
        }
    };
    var person = self();
    person.introduce(); 
    /*
    my name is catnap
    my age is 24
    my height is 176
    */
    
    person.meeting();
    person.introduce();
    /*
    my name is catnap
    my age is 24
    my height is 176
    I have girlfriend // 문장 추가
    */

    비공개 변수가 무엇이고, 클로저가 어떤 건지 생각해보는 시간을 가져보자.

    답은 아래와 같다.

    더보기

    <비공개 변수>

    name, age, height, girlfriend

     

    <클로저>

    { introduce, meeting }

     

    클로저는 사용자가 변수를 조작하지 못하도록 하고 싶을 때 사용한다. 클로저를 사용함으로써 비공개 변수를 갖게 되고, 사용자는 비공개 변수에는 접근을 못하므로 조작을 할 수 없다.

     

    클로저를 설명함에 있어서 스코프와 컨텍스트, 비공개 변수와 함수의 관계 또한 중요한데, 이는 아래의 제로초님의 블로그를 통해 이해하도록 하자.

     

    ZeroCho - 클로저

     


    갑자기 든 의문을 고민하다가 나같은 고민을 한 사람이 있을까봐 새로운 예시를 만든다.

    var addName = (function (){
        var name = ['catnap'];
        function add(anotherName){
            name.push(anotherName);
            console.log(name);
        }
    	return add;
    })();
    
    var haenNap = addName;
    haenNap("haen") // ["catnap", "haen"]
    haenNap("cat") // ["catnap", "haen", "cat"]

    위의 예시에서 haenNap = addName의 과정에서 addName이 IFFE이고 return 값이 add 함수이기 때문에 , 결국 haenNap === add이지 않냐? 라는 의문이 들 수 있다. 

     

    허나 결론부터 말하자면 틀렸다. haenNap === addName이다. addName이 호출될 때, return 값이 add 함수일 뿐, addName === add가 아니기 때문이다.

     

    또 다른 의문은 name이라는 변수가 어떻게 계속 저장될 수 있나에 관한 것이다. addName이 함수이며 name은 그 안의 변수이므로 haenNap이 실행될 때마다 계속 저장되는 것이 아니라 초기화되어야 하는 것이 아닌가였다.

     

    function greet(name){
        var nickname = ['catnap'];
        nickname.push(name);
        console.log(nickname)
    }
    var hello = greet;
    hello("haen") // (2) ["catnap", "haen"]
    hello("cat") // (2) ["catnap", "cat"]

    위의 예시에선 계속 저장되는 게 아닌 초기화 되는 걸 확인할 수 있다.

     

    나는 이렇게 이해하였다.

    a라는 변수에 비공개 변수와 클로저를 지닌 함수를 할당하는 경우, a를 그저 함수가 아닌, 하나의 객체라고 인식하는 것이다.
    (정확하게는 할당이 아닌 참조이지만, 그건 넘어가도록 하겠다.)

    위의 예시에서 haenNap을 addName이라는 함수라고 이해하는 것이 아닌, add라는 클로저 함수와 name이라는 비공개 변수를 가진 유사 객체라고 이해하면 도움이 된다. 비공개 변수이기 때문에 실제 객체에서 변수에 직접 접근하는 방식이 통하진 않지만, 클로저를 통해 비공개 변수를 사용할 수 있다. 

     

    위의 설명은 그저 내가 멋대로 이해한 것이기 때문에 정확하지 않다. 하지만 유사 객체라고 이해하면, 클로저를 이해하고 사용하는 데 큰 무리가 없고, 나같은 의문을 가진 사람들에게는 크게 도움이 되지 않았을까? 조심스레 생각해본다.

     

    (정확한 이유를 알게 되면 나중에 다시 수정하도록 하겠다!)

     

     

     

     

    댓글

Designed by Tistory.