Javascript Closure의 이해




       윤지수




2012년 6월 20일 수요일
문서의 목표 !


       Closure가 어떤 것인지 이해하고,
       이를 잘못 사용하면 어떤 문제가 생기는지,
       그 해법은 무엇인지 이해한다




2012년 6월 20일 수요일
관련 지식

       1. Functional Programming
       >   함수가 인자나 반환값으로도 사용 될 수 있는 프로그래밍 방식으로, 보다 확장성있는 코드구현이 가능

       2. Execution Context
       > 함수가 실행되는 경우 동작에 필요한 정보를 담고 있는 가상의 공간 (추상화된 개념)
       > Value Object 라고도 함


       3. Immediate Function
       >   익명함수라고도 하며 “(function(){ })()” 와 같은 syntax를 가지고 있음
       >   별도 Execution Context영역을 가지고 있어 private한 코드를 작성할 때 유용




2012년 6월 20일 수요일
Closure - 이해하기
       사전 지식 - Javascript의 지역변수와 전역변수

       1.   ‘var’ keyword로 선언한 지역변수는 함수 내부에서만 그 유효범위를 가짐
       2.   지역변수를 외부에서 사용하려면 전역변수로 선언해야 함
       3.   전역변수는 코드통합에 문제가 생겨 그 사용을 지양함
       4.   전역변수를 사용하지 않고도 지역변수를 함수 외부에서 사용 ??




2012년 6월 20일 수요일
Closure - 이해하기
       사전 지식 - Javascript의 지역변수와 전역변수

       1.   ‘var’ keyword로 선언한 지역변수는 함수 내부에서만 그 유효범위를 가짐
       2.   지역변수를 외부에서 사용하려면 전역변수로 선언해야 함
       3.   전역변수는 코드통합에 문제가 생겨 그 사용을 지양함
       4.   전역변수를 사용하지 않고도 지역변수를 함수 외부에서 사용 ??

            : Closure로 가능




2012년 6월 20일 수요일
Closure - 이해하기
       Closure 란 ?

       1. Closure에 대한 여러가지 정의들
       >   함수가 정의되는 순간의 환경을 기억하는 함수. 즉 함수 외부에 선언된 변수를 참조하는 함수
       >   Closure는 변수 자신들이 바인드되는 환경에 한정되지 않는 변수를 가지는 표현식
       > 자신이 생성된 함수의 context에 직접 접근(참조)할 수 있는 함수




                              Context
                    Context




2012년 6월 20일 수요일
Closure - 이해하기
       Closure 란 ?

       1. Closure에 대한 여러가지 정의들
       >   함수가 정의되는 순간의 환경을 기억하는 함수. 즉 함수 외부에 선언된 변수를 참조하는 함수
       >   Closure는 변수 자신들이 바인드되는 환경에 한정되지 않는 변수를 가지는 표현식
       > 자신이 생성된 함수의 context에 직접 접근(참조)할 수 있는 함수




                                        Closure는,
                              Context
                                        함수라고도 하고,
                    Context
                                        상황이라고도 하고,
                                        유효범위(scope or code block)
                                        라고도 함
2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드- 지역변수를 참조하는 예

        function outer() {
          var localVar = 1;
          return function closureFun() {
                    return localVar ++;
                 };

        }

        var funtypevar = outer();
        functypevar();



       1.closureFun 는 closure function으로, outer function이 반환하여 실행 함
       2.closureFun 는 outer함수 context의 localVar를 참조하고 있음




2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드 - 지역변수를 참조하는 예
        function outer() {
          var innervar = 1;
          return function closureFun() {
                    return innervar++;
                 };
        }
        var funtypevar = outer();
        functypevar();



                   outer context                         outer context
                   variable innervar
                                                          variable innervar
                                           Call
                                          outer();
              closureFun context       functypevar()

                                                        closureFun context



       closureFun context에서 outer context를 계속 참조하고 있음


2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드 - 지역함수를 참조하는 예
       지역변수 뿐만 아니라, 함수내 지역함수(inner function)에도 접근(참조)


        function outer() {
          var innervar = 1;
          function inner () {
            return innervar + 10;
          }

            return function closureFun() {
                      var value1 = inner;
                      return value1;
                   };

        }




2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드 - 지역함수를 참조하는 예
       function outer() {
         var innervar = 1;
         function inner () {
           return innervar + 10;
         }

          return function closureFun() {
                    var value1 = inner;
                    return value1;
                 };

       }
       var innerVal = outer();         //function inner body
       innerVal()(); // 11



                   outer context                                         outer context
                   variable innervar
                                                                          variable innervar
                                                 Call “outer function”
                   inner context                        outer();           inner context

               closureFun context                                                   innervar, inner
                                                                                         참조

                                                                         closureFun context


       closureFun context에서 outer context의 inner함수와, innervar변수를 계속 참조하고 있음

2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드 - 비동기 상황의 예1
       > event handler
       > setTimeout



       event handler 를 loop를 통해서 등록하는 예

        window.onload = function() {
            for(var i=1; i < 3; i++ ) {
                document.getElementById("btn" + i).
                addEventListener("click” ,function() { alert(i); },
                false);
             }
        }




2012년 6월 20일 수요일
Closure - 이해하기
       Closure 예제 코드 - 비동기 상황의 예2
       > event handler
       > setTimeout



       settimeout 함수에 callback으로 등록 하는 예
        function testfun() {
          var x = 10;
          window.setTimeout(function(){
            alert(x);
            x++;
          }, 5000);

            window.setTimeout(function(){
              alert(x);
            }, 10000);

            alert("end of function")
        }

        testfun();    //”end of function” --> 10 --> 11 순으로 출력


2012년 6월 20일 수요일
Closure - 이해하기
       Closure를 좀더 잘 알아야 할 이유 !

       Closure는 문제를 일으킬 수 있는 부분이 있어 주의해야하며,
       활용 방법에 따라 언어의 단점을 보완할 수도 있음


       1. 주의 할 점
       >   Closure를 잘못 사용해서 생기는 오류를 조심해야 함


       2. 장점 활용
       Javascript 언어의 단점중 하나인 ‘전역변수’로 인한 문제를 Closure를 통해 해결할 수 있음




2012년 6월 20일 수요일
Closure - 이해하기
       주의 할 점 - Closure 여러번 호출하기
       상황
       Closure function를 여러번 호출해야 하는 경우

       function outer() {
         var innervar = 1;
         return function closureFun() {

                        return innervar++;
                   };

       }

       var innerfun = outer();
       var temp1 = innerfun();
       var temp2 = innerfun();
       var temp3 = innerfun();
       console.log(temp1+ " : " + temp2 + " : " + temp3);

       > temp1, temp2, temp3은 각각 어떤 값을 가지게 될까요?



2012년 6월 20일 수요일
Closure - 이해하기
       주의 할 점 - Closure 여러번 호출하기
       상황
       Closure function를 여러번 호출해야 하는 경우

       function outer() {
         var innervar = 1;
         return function closureFun() {

                        return innervar++;
                   };

       }

       var innerfun = outer();
       var temp1 = innerfun();
       var temp2 = innerfun();
       var temp3 = innerfun();
       console.log(temp1+ " : " + temp2 + " : " + temp3);

       > 각각 1,2,3 이 출력. innervalue 변수를 참조하여 계속 증가 됨



2012년 6월 20일 수요일
Closure - 이해하기
       주의 할 점 - 잘못된 사용의 예
       상황
       화면의 두개의 button UI를 클릭하면 각각 다른 값을 출력
       : 1번버튼을 누르면 1을 출력, 2번버튼을 누르면 2를 출력


        window.onload = function() {
            for(var i=1; i < 3; i++ ) {
                document.getElementById("btn" + i). //btn1,btn2 이라는 id를 가진 태그 찾기
                addEventListener("click",           //click Event listener
                   function() { alert(i); },        //Event handler등록 (각 번호를 출력)
                false);
             }
        }




       > button을 두 개를 클릭 할 때 각각 어떤 값이 노출될까요?




2012년 6월 20일 수요일
Closure - 이해하기
       주의 할 점 - 잘못된 사용의 예
        window.onload = function() {
            for(var i=1; i < 3; i++ ) {
                document.getElementById("btn" + i). //btn1,btn2 이라는 id를 가진 태그 찾기
                addEventListener("click",           //click Event listener
                   function() { alert(i); },        //Event handler등록 (각 번호를 출력)
                false);
             }
        }


         i = 1 일때
        btn1 -> function(){alert(1)}

         i = 2 일때
        btn2 -> function(){alert(2)}
        btn1 -> function(){alert(2)}     // 참조하고 있는 i가 2로 변경

         i++   구문 통과 후 i = 3 일때
        btn3   -> function(){alert(3)}
        btn2   -> function(){alert(3)}   // 참조하고 있는 i가 3으로 변경
        btn1   -> function(){alert(3)}   // 참조하고 있는 i가 3으로 변경




       > i 는 참조 된 것으로 그 값이 변경되는 경우 계속 업데이트 반영 됨

2012년 6월 20일 수요일
Closure - 이해하기
       주의 할 점 - 잘못된 사용의 해결
       참조하고 있는 변수(i)의 관계를 끊기
       >immediate function을 활용하면서 중간과정에서 별도 파라미터를(otherVal) 통해 클로저 상황이 아닌 다른 메모리 영
       역을 바라보게 함




       window.onload = function() {
           for(var i=1; i < 3; i++ ) {
             (function(otherVal) {
               document.getElementById("btn" + otherVal).addEventListener("click",function() {
                   alert(otherVal);
               }, false);
             })(i);
           }
       }




        i의 값은 인자로 할당되지만 otherVal라는 변수로 대체되어 event handler
        로 등록된다. 이것은 변수 i의 참조와의 연결을 끊는 것임




2012년 6월 20일 수요일
End




       참고 사이트
       본문의 내용/소스코드 일부는 아래 사이트에서 참고 되었습니다

       http://en.wikipedia.org/wiki/Closure_(computer_science)
       http://blog.outsider.ne.kr/506
       http://blog.naver.com/bitofsky/50116354883?viewType=pc
       http://msdn.microsoft.com/en-us/magazine/ff696765.aspx
       http://nodejs-kr.org/insidejs/archives/508




2012년 6월 20일 수요일

Javascript Closure

  • 1.
    Javascript Closure의 이해 윤지수 2012년 6월 20일 수요일
  • 2.
    문서의 목표 ! Closure가 어떤 것인지 이해하고, 이를 잘못 사용하면 어떤 문제가 생기는지, 그 해법은 무엇인지 이해한다 2012년 6월 20일 수요일
  • 3.
    관련 지식 1. Functional Programming > 함수가 인자나 반환값으로도 사용 될 수 있는 프로그래밍 방식으로, 보다 확장성있는 코드구현이 가능 2. Execution Context > 함수가 실행되는 경우 동작에 필요한 정보를 담고 있는 가상의 공간 (추상화된 개념) > Value Object 라고도 함 3. Immediate Function > 익명함수라고도 하며 “(function(){ })()” 와 같은 syntax를 가지고 있음 > 별도 Execution Context영역을 가지고 있어 private한 코드를 작성할 때 유용 2012년 6월 20일 수요일
  • 4.
    Closure - 이해하기 사전 지식 - Javascript의 지역변수와 전역변수 1. ‘var’ keyword로 선언한 지역변수는 함수 내부에서만 그 유효범위를 가짐 2. 지역변수를 외부에서 사용하려면 전역변수로 선언해야 함 3. 전역변수는 코드통합에 문제가 생겨 그 사용을 지양함 4. 전역변수를 사용하지 않고도 지역변수를 함수 외부에서 사용 ?? 2012년 6월 20일 수요일
  • 5.
    Closure - 이해하기 사전 지식 - Javascript의 지역변수와 전역변수 1. ‘var’ keyword로 선언한 지역변수는 함수 내부에서만 그 유효범위를 가짐 2. 지역변수를 외부에서 사용하려면 전역변수로 선언해야 함 3. 전역변수는 코드통합에 문제가 생겨 그 사용을 지양함 4. 전역변수를 사용하지 않고도 지역변수를 함수 외부에서 사용 ?? : Closure로 가능 2012년 6월 20일 수요일
  • 6.
    Closure - 이해하기 Closure 란 ? 1. Closure에 대한 여러가지 정의들 > 함수가 정의되는 순간의 환경을 기억하는 함수. 즉 함수 외부에 선언된 변수를 참조하는 함수 > Closure는 변수 자신들이 바인드되는 환경에 한정되지 않는 변수를 가지는 표현식 > 자신이 생성된 함수의 context에 직접 접근(참조)할 수 있는 함수 Context Context 2012년 6월 20일 수요일
  • 7.
    Closure - 이해하기 Closure 란 ? 1. Closure에 대한 여러가지 정의들 > 함수가 정의되는 순간의 환경을 기억하는 함수. 즉 함수 외부에 선언된 변수를 참조하는 함수 > Closure는 변수 자신들이 바인드되는 환경에 한정되지 않는 변수를 가지는 표현식 > 자신이 생성된 함수의 context에 직접 접근(참조)할 수 있는 함수 Closure는, Context 함수라고도 하고, Context 상황이라고도 하고, 유효범위(scope or code block) 라고도 함 2012년 6월 20일 수요일
  • 8.
    Closure - 이해하기 Closure 예제 코드- 지역변수를 참조하는 예 function outer() { var localVar = 1; return function closureFun() { return localVar ++; }; } var funtypevar = outer(); functypevar(); 1.closureFun 는 closure function으로, outer function이 반환하여 실행 함 2.closureFun 는 outer함수 context의 localVar를 참조하고 있음 2012년 6월 20일 수요일
  • 9.
    Closure - 이해하기 Closure 예제 코드 - 지역변수를 참조하는 예 function outer() { var innervar = 1; return function closureFun() { return innervar++; }; } var funtypevar = outer(); functypevar(); outer context outer context variable innervar variable innervar Call outer(); closureFun context functypevar() closureFun context closureFun context에서 outer context를 계속 참조하고 있음 2012년 6월 20일 수요일
  • 10.
    Closure - 이해하기 Closure 예제 코드 - 지역함수를 참조하는 예 지역변수 뿐만 아니라, 함수내 지역함수(inner function)에도 접근(참조) function outer() { var innervar = 1; function inner () { return innervar + 10; } return function closureFun() { var value1 = inner; return value1; }; } 2012년 6월 20일 수요일
  • 11.
    Closure - 이해하기 Closure 예제 코드 - 지역함수를 참조하는 예 function outer() { var innervar = 1; function inner () { return innervar + 10; } return function closureFun() { var value1 = inner; return value1; }; } var innerVal = outer(); //function inner body innerVal()(); // 11 outer context outer context variable innervar variable innervar Call “outer function” inner context outer(); inner context closureFun context innervar, inner 참조 closureFun context closureFun context에서 outer context의 inner함수와, innervar변수를 계속 참조하고 있음 2012년 6월 20일 수요일
  • 12.
    Closure - 이해하기 Closure 예제 코드 - 비동기 상황의 예1 > event handler > setTimeout event handler 를 loop를 통해서 등록하는 예 window.onload = function() { for(var i=1; i < 3; i++ ) { document.getElementById("btn" + i). addEventListener("click” ,function() { alert(i); }, false); } } 2012년 6월 20일 수요일
  • 13.
    Closure - 이해하기 Closure 예제 코드 - 비동기 상황의 예2 > event handler > setTimeout settimeout 함수에 callback으로 등록 하는 예 function testfun() { var x = 10; window.setTimeout(function(){ alert(x); x++; }, 5000); window.setTimeout(function(){ alert(x); }, 10000); alert("end of function") } testfun(); //”end of function” --> 10 --> 11 순으로 출력 2012년 6월 20일 수요일
  • 14.
    Closure - 이해하기 Closure를 좀더 잘 알아야 할 이유 ! Closure는 문제를 일으킬 수 있는 부분이 있어 주의해야하며, 활용 방법에 따라 언어의 단점을 보완할 수도 있음 1. 주의 할 점 > Closure를 잘못 사용해서 생기는 오류를 조심해야 함 2. 장점 활용 Javascript 언어의 단점중 하나인 ‘전역변수’로 인한 문제를 Closure를 통해 해결할 수 있음 2012년 6월 20일 수요일
  • 15.
    Closure - 이해하기 주의 할 점 - Closure 여러번 호출하기 상황 Closure function를 여러번 호출해야 하는 경우 function outer() { var innervar = 1; return function closureFun() { return innervar++; }; } var innerfun = outer(); var temp1 = innerfun(); var temp2 = innerfun(); var temp3 = innerfun(); console.log(temp1+ " : " + temp2 + " : " + temp3); > temp1, temp2, temp3은 각각 어떤 값을 가지게 될까요? 2012년 6월 20일 수요일
  • 16.
    Closure - 이해하기 주의 할 점 - Closure 여러번 호출하기 상황 Closure function를 여러번 호출해야 하는 경우 function outer() { var innervar = 1; return function closureFun() { return innervar++; }; } var innerfun = outer(); var temp1 = innerfun(); var temp2 = innerfun(); var temp3 = innerfun(); console.log(temp1+ " : " + temp2 + " : " + temp3); > 각각 1,2,3 이 출력. innervalue 변수를 참조하여 계속 증가 됨 2012년 6월 20일 수요일
  • 17.
    Closure - 이해하기 주의 할 점 - 잘못된 사용의 예 상황 화면의 두개의 button UI를 클릭하면 각각 다른 값을 출력 : 1번버튼을 누르면 1을 출력, 2번버튼을 누르면 2를 출력 window.onload = function() { for(var i=1; i < 3; i++ ) { document.getElementById("btn" + i). //btn1,btn2 이라는 id를 가진 태그 찾기 addEventListener("click", //click Event listener function() { alert(i); }, //Event handler등록 (각 번호를 출력) false); } } > button을 두 개를 클릭 할 때 각각 어떤 값이 노출될까요? 2012년 6월 20일 수요일
  • 18.
    Closure - 이해하기 주의 할 점 - 잘못된 사용의 예 window.onload = function() { for(var i=1; i < 3; i++ ) { document.getElementById("btn" + i). //btn1,btn2 이라는 id를 가진 태그 찾기 addEventListener("click", //click Event listener function() { alert(i); }, //Event handler등록 (각 번호를 출력) false); } } i = 1 일때 btn1 -> function(){alert(1)} i = 2 일때 btn2 -> function(){alert(2)} btn1 -> function(){alert(2)} // 참조하고 있는 i가 2로 변경 i++ 구문 통과 후 i = 3 일때 btn3 -> function(){alert(3)} btn2 -> function(){alert(3)} // 참조하고 있는 i가 3으로 변경 btn1 -> function(){alert(3)} // 참조하고 있는 i가 3으로 변경 > i 는 참조 된 것으로 그 값이 변경되는 경우 계속 업데이트 반영 됨 2012년 6월 20일 수요일
  • 19.
    Closure - 이해하기 주의 할 점 - 잘못된 사용의 해결 참조하고 있는 변수(i)의 관계를 끊기 >immediate function을 활용하면서 중간과정에서 별도 파라미터를(otherVal) 통해 클로저 상황이 아닌 다른 메모리 영 역을 바라보게 함 window.onload = function() {     for(var i=1; i < 3; i++ ) { (function(otherVal) {         document.getElementById("btn" + otherVal).addEventListener("click",function() {             alert(otherVal);         }, false);     })(i); } } i의 값은 인자로 할당되지만 otherVal라는 변수로 대체되어 event handler 로 등록된다. 이것은 변수 i의 참조와의 연결을 끊는 것임 2012년 6월 20일 수요일
  • 20.
    End 참고 사이트 본문의 내용/소스코드 일부는 아래 사이트에서 참고 되었습니다 http://en.wikipedia.org/wiki/Closure_(computer_science) http://blog.outsider.ne.kr/506 http://blog.naver.com/bitofsky/50116354883?viewType=pc http://msdn.microsoft.com/en-us/magazine/ff696765.aspx http://nodejs-kr.org/insidejs/archives/508 2012년 6월 20일 수요일