JavaScript Closure

[mozilla] https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures 에서의 closure 설명

closure?

  • Closure는 함수와 그 함수가 만들어질 때의 환경으로 이루어진 object. 환경에는 closure가 생성 될 때 사용할 수 있었던(scope에 있던) 변수로 구성되어 있음
  • 예제
function makeFunc() {
  var name = "Mozilla";
  function displayName() {
    alert(name);
  }
  return displayName;
}

var myFunc = makeFunc();
myFunc();
  • 위 예제에서 myFunc는 closure를 갖는다. closure는 displayName 함수와 “Mozilla” string으로 구성되어 있다.
  • myFunc가 closure를 갖기 때문에 makeFunc 함수 내부 지역변수인 name에 접근가능한 것이 설명이 된다.

[understand-javascript-closures-with-ease] http://javascriptissexy.com/understand-javascript-closures-with-ease/, JavaScript Definite Guide 읽고 정리함.

closure?

  • function object와 variable scope의 조합을 closure라고 함.
  • JavaScript는 lexical scoping 사용.
  • lexical scoping은 함수가 정의되었을 때의 variable scope를 사용하여 함수가 실행되는 것.
  • 참고로 함수가 수행되는 시점의 variable scope를 사용하는 것은 dynamic scoping이라고 불리며 Lips 언어에서 처음 사용.
  • lexical scoping 예제 (http://stackoverflow.com/questions/1047454/what-is-lexical-scope 참고)
var x = 10;

function fun()
{
    var x = 5;
    function fun2()
    {
        console.log(x);
    }
    return fun2;
}

fun()();
  • 위 예제에서 fun()()에 의해 fun2가 호출되게 되는데 fun2는 x를 출력함. JS는 lexical scoping이므로 fun2가 정의된 시점의 variable scope를 가짐. 정의된 시점에서 보면 fun2는 fun의 inner 함수. 호출 시점에서 보면 전역함수에서 fun2()를 호출. inner 함수는 outer 함수의 variable에 접근 가능. 따라서 fun2는 fun의 variable에 접근 가능. 따라서 x는 5가됨.
function fun()
{
    console.log(x);
}

function dummy1()
{
    var x = 5;
    fun();
}
function dummy2()
{
    var x = 10;
    fun();
}
dummy1();
dummy2();
  • 위 예제는 dynamic scoping의 예제. JS가 dynamic scoping이라면 dummy1이 호출되면 x는 5, dummy2가 호출되면 x는 10이 되어야 겠지만. static scoping이므로 x는 undefined이 된다.

Closure in a nested function

  • nested function이 사용될 때 closures는 흥미로워 짐.
  • closure는 어떤 function 수행 시, local variable을 캡처해서 그 variable을 private 변수로 사용하는 것처럼 사용.
var scope = "global scope";
function checkscope() {
    var scope = "local scope";
    function f() { return scope; }
    return f;
}
checkscope()()
  • 위 코드에서 checkscope 함수의 scope는 지역변수라 함수 밖에서는 접근 못함.
  • 하지만 중첩함수를 함수 밖에서 호출한다면 지역변수 scope에 접근 가능.
  • 왜냐하면 function의 variable scope는 함수가 정의될 때 결정되기 때문. 부연설명하면 모든 inner function은 outer function의 변수에 접근 가능. 위 예제에서 function f는 정의될 시점에 checkscope가 outer function이므로 checkscope에 정의된 변수 scope에 접근 가능. dynamic scoping일 경우에는 f를 호출하고 있는 함수가 전역함수이므로 global scope가 출력될 것이라 생각됨.

  • inner function은 outer function의 파라미터에도 접근할 수 있음.

  • inner function은 outer function의 argument에는 접근 못함.

Call by reference

  • closure는 outer function이 return해서 끝난 뒤에도 outer function의 variable에 접근 가능
  • closure는 outer function의 variable 값을 가지고 있는 것이 아니라 참조값을 가짐. 따라서 outer function의 variable의 최신 값을 가져오거나 새로운 값으로 변경 가능 (call by reference)
  • for loop 안에서 배열에 inner 함수를 저장할 경우, inner function에 for loop의 변수 i가 사용되면 나중에 inner 함수 출력할 때, 기대했던 i값이 안나옴. inner function이 outer function variable의 참조값을 저장하므로 i값은 for loop에 의해 for loop 끝날때까지 변경되었음. 이를 해결하기 위한 방안으로 Immediately Invoked Function Expression (IIFE)가 있음.
  • IIFE 예제
    http://stackoverflow.com/questions/21487187/why-is-the-loop-assigning-a-reference-of-the-last-index-element-to 참고
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s