ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Effective JavaScript [11] - 클로저에 익숙해져라
    Javascript 2016. 12. 5. 22:59



    본 게시물은 Effective Javascript의 내용을 재구성하여 작성되었음을 알립니다. 저작권 문제 발생시 게시물이 비공개 될 수 있습니다. 


    - 함수는 외부 스코프에 선언된 변수를 참조할 수 있다.

    - 클로저는 자신을 생성한 함수보다 더 오래 지속된다.

    - 클로저는 내부적으로 외부 변수에 대한 참조를 저장하고, 저장된 변수를 읽고 갱신할 수 있다.



    클로저(closure)를 지원하지 않은 언어를 사용하던 프로그래머에게는 친근하지 않을 개념일 수 있다. 클로저를 이해하는 데는 세가지의 기본적인 사실만 배우면 된다. 


    첫 번째로는 자바스크립트는 현재 함수 외부에서 선언된 변수를 참조할 수 있다.


    function makeSandwich() {

        var magicIngredient = "peanut butter";

        function make(filling) {

            return magicIngredient + " and " + filling;

        }

        return make("jelly");

    }


    makeSandwich();    // "peanut butter and jelly


    내부의 make 함수가 이 함수 바깥에서 선언된, 다시말하면 magicIngredient함수에서 선언된 makeSandwich 변수를 참조한다는 사실을 주목하라.



    두 번째로는 함수는 외부 함수가 무엇인가 리턴한 이후에도 이 외부 함수에 선언된 변수를 참조할 수 있다. 이 사실이 이해하기 힘들다면, 자바스크립트 함수가 일종의 객체라는 사실을 기억하라. 이는 내부 함수를 리턴할 수 있고, 이 함수가 나중에 다시 호출될 수 있다는 뜻이다.


    function sandwichMaker() {

        var magicIngredient = "peanut butter";

        function make(filling) {

            return magicIngredient = " and " + filling;

        }

        return make;

    }


    var f = sandwichMaker();

    f("jelly");        // "peanut butter and jelly"

    f("bananas");    // "peanut butter and bananas"

    f("marshmallows");    // "peanut butter and marshmallows"


    위 예제는 외부 함수에서 make("jelly")를 곧바로 호출하는 대신에 sandwichMaker가 make 함수 자체를 리턴한다는 점을 빼고는 첫 번째 예제와 동일하다. f 의 값은 내부의 make 함수이고 f를 호출하는 것은 maker 를 효과적으로 호출하는 셈이 된다. sandwichMaker 가 리턴되었더라도 make 함수는 어찌되었든 magicIngredient 값을 기억하고 있다. 


    자바 스크립트 함수 값은 호출되었을 때 실행되기 위한 코드 뿐만 아니라 더 많은 정보를 포함하고 있기 때문에 가능하다. 자바스크립트 함수는 해당 스코프에서 선언되어 참조할 수 있는 어떤 변수라도 내부적으로 보관한다. 함수 자신이 포함하는 스코프의 변수들을 추적하는 함수를 클로저라고 한다. make 함수는 magicIngredient와 filling  두 개의 외부 변수를 참조하는 클로저다. 언제든 make 함수가 호출되면 이 두 변수가 클로저에 저장되어 있기 때문에 참조할 수 있다.


    함수는 파라미터와 외부 함수의 변수뿐만 아니라 해당 스코프 내에 포함된 어떤 변수라도 참주할 수 있다. 이를 더 보편적으로 사용할 수 있는 sandwichMaker 함수를 만들 수 있다.


    function sandwichMaker(magicIngredient) {

        function make(filling){

            return magicIngredient + " and " + filling;

        }

        return make;

    } 


    var hamAnd = sandwichMaker("ham");

    hanAnd("cheese");        // "ham and cheese";

    hamAnd("mustard");    // "ham and mustard";

    var turkeyAnd = sandwichMaker("turkey");

    turkeyAnd("Swiss");        // turkey and Swiss"

    turkeyAnd("Provolone");    // turkey and Provolone"


    이 예제는 hamAnd와 turkeyAnd 두 개의 다른 함수를 생성한다. 두 함수가 동일한 make 정의에 의해 만들어 짐에도 불구하고, 이들은 두 개의 서로 다른 객체다. 첫 번째 함수에서 magicIngredient의 값은 "ham"이고 두 번째 함수에서는 "turkey"이다. 


    클로저는 자바스크립트에서 가장 우아하고 표현력이 높은 기능 중 하나이고, 많은 유용한 코딩 관례들의 중심이 된다. 자바스크립트는 클로저를 생성하기 위해 더 편리하고 일반적인 문법을 제공하는데, 함수 표현식이 바로 그것이다.


    function sandwichMaker(magicIngredient) {

        return function(filling) {

            return magicIngredient + " and " + filling;

        };

    }


    함수 표현식이 익명인 사실에 주목해야 한다. 지역적으로 호출하기 위한 용도가 아닌 새로운 함수값을 만들기 위해 평가하는 용도로 만들어졌기 때문에 이름을 지을 필요가 없다. 



    세 번째로 기억해야 할 사실은 클로저가 외부 변수의 값을 변경할 수 있다는 점이다. 클로저는 외부 변수의 값을 복사하지 않고 참조를 저장한다. 따라서 그들에게 접근하는 어떤 클로저도 변경사항을 볼 수 있다.  아래의 box 객체는 내부의 값을 가지며 그 값을 읽고 변경할 수 있는 객체다.


    function box() {

        var val = undefined;

        return { 

            set : function(newVal) { val = newVal; } , 

            get : function() { return val; },

            type : function() { return typeof val; }

        };

    }


    var b = box();

    b.type();     // "undefined"

    b.set(98.6);

    b.get();    // 98.6

    b.type();    // "number"


    위 예제는 세개의 클로저, 즉 set, get, type 프로퍼티들을 포함하는 객체를 생성한다. 각 클로저는 var 변수를 공유하여 접근한다. set 클로저로 val 의 값을 변경하고, 그 이후에 get과 type을 호출해 변경에 대한 결과를 확인한다.



    - 함수는 외부 스코프에 선언된 변수를 참조할 수 있다.

    - 클로저는 자신을 생성한 함수보다 더 오래 지속된다.

    - 클로저는 내부적으로 외부 변수에 대한 참조를 저장하고, 저장된 변수를 읽고 갱신할 수 있다.



Designed by Tistory.