민서네집

클로져(Closure)를 이용한 체인 깨기 본문

Javascript

클로져(Closure)를 이용한 체인 깨기

브라이언7 2013. 5. 1. 11:24

[참조] 실시간 웹 애플리케이션 개발을 위한 Node.js 프로그래밍 - 류성태 지음 (프리렉 출판사)


44~48 page


클로져는 자신의 범위 밖에 있는 변수에도 접근할 수 있는 함수를 의미한다.

<!DOCTYPE html>
<script type="text/javascript">

  function f() {
    var b = "b";
    return function() {
      return b;
    }
  }

  var n = f();
  alert( n() ); // b
</script>
function f 의 내부변수 b 를 private 멤버변수라고 생각해보면,
클로져를 이용해서 private 멤버변수를 get 하는 함수를 다음과 같이 만들 수 있다.

<!DOCTYPE html>
<script type="text/javascript">

  function f() {
    var b = "b";
    this.getB = function() {
      return b;
    };
  }

  var n = new f();
  alert( n.b );       // undefined
  alert( n.getB() );  // b
</script>


<!DOCTYPE html> <script type="text/javascript"> function f(arg) { var n = function() { return arg; } arg++; return n; } var m = f(123); alert( m() ); // 124 </script>

var n = function() { return arg; } 는 함수 선언만 된 것이고, 이 함수가 실행되는 것은 alert( m() ); 을 할 때이다.
그런데 var m = f(123); 문장에서 함수 f의 내부변수인 arg는 이미 124 로 증가된 상태이다.
따라서 124 를 alert 하게 된다.

<!DOCTYPE html>
<script type="text/javascript">
  function f(){
    var a=[];
    var i;
    for(i=0; i<3; i++){
      a[i] = function(){
        return i;
        }
    }
    return a;
  }
  
  var b = f();
  alert( b[0]() ); // 3
  alert( b[1]() ); // 3
  alert( b[2]() ); // 3
</script>

0, 1, 2 가 차례로 alert 되는 결과를 예상할 수 있지만, 실제는 그렇지 않다.

a[i] = function() { return i;} 

는 함수 선언만 된 것이고 실제로 이 함수가 실행되는 것은 alert( b[0]() ); 명령을 만났을 때인데,

var b = f(); 문장에서 for loop문의 실행이 끝나고 i 값이 이미 3 으로 되어 있기 때문에 3 이 alert 되는 것이다.


<!DOCTYPE html>
<script type="text/javascript">
  function f(){
    var a=[];
    var i;
    for(i=0; i<3; i++){
      a[i] = (function(x) { 
        return function(){
          return x;
        }
      })(i);
    }
    return a;
  }
  
  var b = f();
  alert( b[0]() ); // 0
  alert( b[1]() ); // 1
  alert( b[2]() ); // 2
</script>

function 내부의 변수인 i를 바로 return 하지 않고, 파라미터를 받는 function을 정의한 다음에

파라미터로 내부 변수 i를 넘겨서 클로저가 내부 변수 i가 아니라 파라미터를 리턴하도록 하는 방법.

function f() 내부에서 a[i] = (function(x) { ... })(i); 로 파라미터를 받는 함수를 이미 실행시켰다는 것에 주의하자.

파라미터는 0, 1, 2를 차례로 받게 되고, 나중에 alert( b[0]() ); 를 실행하더라도 파라미터를 기억하고 있다가 0, 1, 2를 차례로 리턴하게 된다.


<!DOCTYPE html>
<script type="text/javascript">
  function f(){
    var a=[];
    var i;
    for(i=0; i<3; i++){
      a[i] = (function(x) { 
        return function(){
          return x;
        }
      })(i)();
    }
    return a;
  }
  
  var b = f();
  alert( b[0] ); // 0
  alert( b[1] ); // 1
  alert( b[2] ); // 2
</script>

위의 경우 f()의 리턴값인 b 는 클로저가 아니라 배열이다. f() 함수의 선언 내의 for loop 문 안에서 

a[i] = (function(x) { ... })(i)(); 에서 함수가 실행되서 a 배열에 function 이 아니라 값이 할당된다.


<!DOCTYPE html>
<script type="text/javascript">
  function f(){
    var a=[];
    var i;
    for(i=0; i<3; i++){
      a[i] = (function(x) { 
        return x;
      })(i);
    }
    return a;
  }
  
  var b = f();
  alert( b[0] ); // 0
  alert( b[1] ); // 1
  alert( b[2] ); // 2
</script>

위의 경우 전전 예제랑 비슷하지만 for loop 안에서 a[i] 에 할당되는 것이 function(){ return x; } 가 아니라 x; 라는 것이 다르다. 전 예제와 마찬가지로 f() 의 반환값이 클로저가 아니라 배열이다. a 배열의 값의 할당이 funciton f 의 for loop 문 안에서 일어나고, 당연히 0, 1, 2 가 alert 된다.


Comments