javascript의 scope chain과 closure에 대한 설명은 간단히 구글 검색을 해보면, 얼마든지 읽어 볼 수 있습니다. 그럼에도 내가 여기에 다시 이 내용을 정리하는 이유는 내가 스스로 정리할 필요에서 이기도 하고, 내가 이해하고 있는 방식이, 어떤 사람들에게는 좀 더 쉽게 이해 될 수 있기 때문입니다. 
javascript에서의 변수의 유효범위 즉, scope는 직관적으로 이해하기가 쉽지 않다는 것을 javascript를 사용하여 개발해본 경험이 있는 분들은 다들 알고 있을 것입니다. 이 문제는 javascript의 scope chain이라는 주제로 알려져 있으며, javascript를 제대로 이해하기 위한 마지막 문법이라고 볼 수 있을 것 같습니다. javascript에서의 scope chain이란 수 많은 함수 호출의 연결로 이루어져 작성된 코드가 있다고 했을 때, 그 코드의 각 함수내에서 사용하는 변수나 함수가 어느 영역의 것을 참조하게 되는가에 대한 문제입니다. 
이 scope chain의 this 키워드의 사용과는 전혀 관련이 없는데, 이후 혼란을 방지하기 위해서 이 구분을 먼저 하고 가도록 하겠습니다.
var a=1;
function func1(){
    alert(a);
}

func1();   //1)함수 호출

var o = new Object();
o.a = 2;
o.func2 = function func2(){
                 alert(this.a);
              };
o.func2(); //2)메소드 호출

function func3(){
    alert(this.a); //->도대체 this.a는 무엇일까요?
}

func3(); //3)함수 호출

alert(this.a); //4)전역 script

위 코드에서 1)함수 호출에서 보듯이 함수는 어떤 객체와도 연관지어 지지 않은 상태에서 호출된 것입니다. 2)메소드 호출은 객체와 연관되어 있는 함수 있것이지요. this 키워드는 함수안에서 사용되며, 이 함수호출의 대상이 되는 객체를 참조하는 키워드 입니다. 여기서는 o 가 되겠습니다.
그런데. 3)함수 호출의 경우는 어떨까요? 여기에서 사용된 this는 무엇을 의미할까요? 바로 전역객체를 의미합니다. 보통 전역객체는 브라우저에서는 window객체가 됩니다. 브라우저의 javascript엔진은 javascript를 실행하기 전에 전역객체인 window객체를 먼저 만들게 되는 것이지요. 그렇다면 결국은 함수호출도 궁극적으로는 메소드호출이다 말할 수 있으며 그것은 window라는 객체에 대해서 호출된 것입니다. 
마지막입니다. 그럼 4)전역 script의 실행에서 도대체 this는 무엇일까요? 전역객체인 window 객체에 해당합니다. 이것은 무엇을 뜻하냐면, 전역 script는 그 전체가 하나의 가상 함수안의 코드이다라고 말할 수있으며, 그것은 window객체에 대해서 호출되었다라고 해석해 볼 수 있습니다. 여기서 this.a는 예제코드 1라인에서 선언한 a 에 해당합니다.(이에 대한 설명이 좀더 필요한데 아래에서 설명될 것입니다)
결론적으로 말해서, javascript의 모든 코드는 함수안에 존재하는 것이며(심지어 전역script도 가상의 함수의 내부 코드로 생각해볼 수 있다), 궁극적으로는 특정 객체(전역script나 함수호출의 경우는 전역객체)에 대해서 호출되는 메소드이다라고 말할 수 있는 것이고, this라는 키워드는 메소드가 호출되는 대상 객체를 지칭하는 것이지요.
이제 함수와 메소드는 궁극적으로 동일한 것으로 이해되었으니, 아래에서는 모두 함수로 통일합니다.
지금 까지 함수가 실행될 때 함수안에서 참조되는 this라는 객체에 대해서 설명했는데, this처럼 직접 참조할 수는 없지만 암묵적으로 생성되어 사용되는 객체가 하나 더 있습니다. 그것은 바로 실행객체라는 친구입니다. 실행객체는 함수가 호출될 때, 함수 내부의 실행문맥에서 생성되며 함수 내부의 코드상에 선언된 변수와 함수를 property로 저장하고 있는 객체입니다.
함수가 호출될 때 함수내부의 코드가 실행되기 전에 일단 this키워드로 참조되는 객체가 정해지며, 또한, 실행객체가 추가로 생성됩니다. 그런 후에 함수 내부의 코드는 parsing단계와 실행단계를 거칩니다. parsing단계에서 함수내부 코드에 선언된 모둔 변수와 함수가 실행객체의 property로 세팅됩니다. 그런 후에 코드가 실행단계에 이르면, this로 참조되는 변수와 함수는 this객체에서 찾게 되고, 그렇지 않은 변수와 함수는 실행객체에서 찾게 됩니다. 
var a =1 ;
function func(){
   var b =2;
   alert(b); // 1)실행객체에서 b를 찾아낸다.
   alert(this.c)// 2)this 객체에서 c를 찾아낸다.
   alert(a); //3)실행객체에도 없고 this객체에도 없는데 어디서 찾을까요?
}
var o = new Object();
o.c = 3;
o.f = func;

o.f();

그렇다면, 위의 예제 코드 3)라인에서 보여준 것 처럼 this로 참조하는 변수와 함수도 아니고, 내부코드에서 선언되어 실행객체에서 찾을 수도 없는 변수와 함수는 어떻게 찾아 내는 것일까요? 바로 여기서 scope chain의 개념이 시작합니다.
이 이야기를 시작하기 전에 전역객체인 window객체의 역할에 대해서 한가지 더 집고 넘어가야 합니다.
모든 함수는 실행시에 this객체와 실행객체를 가지게 된다고 설명했습니다. 두개의 객체는 전적으로 서로 다른 것입니다. 그런데, 한가지 예외가 있습니다. 전역script의 영역에 해당하는 가상의 함수의 실행의 경우와 오브젝트에 대해서 호출되지 않은 전역함수의 호출의 경우에는 this객체와 실행객체가 구분되지 않는 다는 것입니다. 이 경우에는 window객체가 this객체와 실행객체의 역할을 모두 수해합니다. 따라서, 전역 script영역에서 var 키워드로 선언한 것은 window객체의 property가 되며, 전역script나 전역 함수에서 this키워드로 참조할 수 있는 것입니다. 
이제 scope chain의 문제로 넘어가지요.
scope chain을 이해하기 위한 시작은 함수선언은 그것을 감싸고 있는 외부코드가 parsing되는 단계에서 함수선언을 만나면 함수객체가 만들어지고, 그것이 실행객체에 property로서 세팅되는 시점 부터입니다. 중요한 것은 이 시점에 외부코드의 실행문맥에서 가지고 있는 scope chain이 함수객체에 세팅된다는 것입니다. 이후 함수가 실행될 때 새로이 실행객체가 하나가 더 만들어진 후, 함수객체에 세팅된 scope chain에 더해져서 호출된 함수내부의 실행문맥에서 scope chain을 형성하게 됩니다.
다음의 코드로 이를 더 알기 쉽게 설명해보겠습니다.
//1-0)아래 script 실행시 전역객체가 실행객체의 역할을 함
var a; //1-1)global객체에 저장됨
function outer(){ //1-2)함수 선언이 함수객체가 되어 global객체에 저장됨
   //2-0)코드 실행시 실행객체1이 생성됨
   var b; //2-1)실행객체1에 저장됨
   function inner(){ //2-2)함수선언이 함수객체가 되어 실행객체1에 저장됨
      //3-0)코드 실행시 실행객체2에 저장됨
      var c; //3-1)실행객체 2에 저장돔
      //3-2)아래 코드 호출시 scope chain은 실행객체2->실행객체1->global객체
      alert(a); //global객체에서 발견
      alert(b); //실행객체1에서 발견
      alert©; //실행객체2에서 발견
   }
   inner(); //2-3)이코드 호출시 scope chain 은 실행객체1 -> global객체
}

outer(); //1-3) 이 코드 호출시 scope chain은 global객체

전역 script영역에서는 global객체가 이미 1개 존재하여 실행객체의 역할을 한다고 했던 것을 기억한다면, scope chain은 함수선언이 파싱단계에서 함수객체로 만들어질 때, 그 함수선언을 포함하고 있는 코드의 실행문맥에 존재하는 scope chain을 넘겨 받게 되고, 나중에 이 함수가 실제 호출될 때, 함수객체가 가지고 있는 scope chain에 실행시 새로 생성한 실행객체를 추가하여 scope chain을 구성하게 되는 중첩된 구조라고 이해하면 되겠습니다.

그럼, 다음으로는 javascript 궁극의 문법중의 하나인 closure에 대한 설명을 하겠습니다. closure와 관련된 문제는 함수를 return하는 함수의 경우에도 발생하는 사안입니다.
function outer(x){
    return function inner(){ //함수객체가 만들어질때,  outer함수의 scope chain이 세팅된다.
         alert(x);
    }
}
var inner = outer(3); //1)
inner(); //2)
 1)라인 코드 실행시 outer함수 내부에서는 실행객체가 하나 생성됩니다. 그리고 나서 함수객체를 리턴하는데, 이 함수객체의 scope chain에는 outer함수의 실행객체가 포함되어 있습니다. 다음에 2)라인의 코드가 실행되었을 때, x 라는 변수를 도대체 어디서 참조할까 이상해 보이겠지만, scope chain을 검색하다가 이전에 outer함수실행시 생성되었던 실행객체에서 x라는 변수를 만나게 되는 것입니다.
여기서는 설명 안하겠지만, closure와 관련된 개념을 사용하여, 변수의 은닉화같은 흉내를 낼수도 있다.  closure와 관련한 실용성을 나중에 다시 한번 정리하여 소개할 기회를 갖도록 하겠다.
여기까지 조금 장황하지만, 내가 이해하고 있는 javascript의 scope chain에 대해서 설명하였습니다. 내가 이해하고 있는 방식을 설명하고 있으므로, javascript의 spec의 설명과 일치하지 않는 것도 있겠습니다만, 제 설명이 공감이 가는 분들도 많으시리라고 봅니다. 
핵심이 되는 문장만 따로 정리하자면서 설명을 마치겠습니다.
1)모든 함수는 궁극적으로 객체에 대한 메소드이며 이 객체는 this로서 참조된다.
2)전역 script와 전역함수의 경우에는 대상객체가 window객체이다. 
3)모든 함수의 실행시에 this 객체이외에 실행객체도 하나 생성된다.
4)실행객체는  var 선언 변수와 함수선언을 parsing단계에서 property로 저장한다.
5)전역script와 전역함수의 경우에는 this와 실행객체가 구분되지 않고 모두 window객체이다. 
6)parsing단계에서 함수객체가 생성되며, 이때 현재의 scope chain이 함수객체에 세팅된다.
7)함수호출 시에 새로 생성된 실행객체가 함수개체에 저장된 scope chain에 추가되어 새로운 scope chain을 구성한다.
this is from robert’s blog

Closures

Now when you hopefully have gotten a better grasp of what scope is, let’s add closures to the mix. Closures are expressions, usually functions, which can work with variables set within a certain context. Or, to try and make it easier, inner functions referring to local variables of its outer function create closures. For instance:

1.function add (x) {
2.return function (y) {
3.return x + y;
4.};
5.}
6.var add5 = add(5);
7.var no8 = add5(3);
8.alert(no8); // Returns 8

Whoa, whoa! What just happened? Let’s break it down:

  1. When the add function is called, it returns a function.
  2. That function closes the context and remembers what the parameter x was at exactly that time (i.e. 5 in the code above)
  3. When the result of calling the add function is assigned to the variable add5, it will always know what x was when it was initially created.
  4. The add5 variable above refers to a function which will always add the value 5 to what is being sent in.
  5. That means when add5 is called with a value of 3, it will add 5 together with 3, and return 8.

So, in the world of JavaScript, the add5 function actually looks like this in reality:

1.function add5 (y) {
2.return 5 + y;
3.}

javascript는 함수 실행시에 아래 두 개의 객 체의 도움을 받는다. arguments object: 실행될 함수에 전달된 매 개변수들과 관련된 속성을 가짐 call object 이 두 객체는 함께 동작하며, 다음과 같은 일 반적인 특징을 가진다. javascript 함수를 지원한다. 임시적으로 존재한다. 함수가 실행될 때 만들어졌다가 함수가 종 료되면 사라진다. call object는 argumets object를 참조한다. 이 포인터는 call object의 속성이다. 이 포인터는 “arguments"라는 이름으로 식 별된다.

이 포인터는 argument object이 속성에 접 근시에 사용된다. 이 포인터는 함수 실행 시 함수 몸체에서 사 용할 수 있다.
[the call object description]
call object는 특별한 임시 객체로 함수가 실 행되는 동안 존재한다. call object는 두 가지 중요한 목적을 가진다. argument object를 가리키는 포인터를 제공 한다. 함수 실행 시 scope chain을 관장한다. call object는 이 외의 다른 속성이나 기능이 없다.
[the pointer to the arguments object]
call object는 argument object를 가리키는 포인터를 제공한다. 이 속성이 바로 arguments 속성이다. arguments 속성을 통 해 argument object의 속성에 접근할 수 있 다.

javascript는 왜 arguments 속성을 call object에 넣어두었을까? 이유는 다음과 같 다. arguments object는 native object가 아니기 때문에 인스턴스를 만드는 등, 끌어다 쓸 방 법이 없다. 즉, arguments object의 속성에 접근할 수 있는 방법이 없는거다. 그래서 call object에 arguments object를 가리키는 포인터(속성)을 제공하는 것이다. call object 와 arguments object는 함수 실행시에 동시 에 만들어졌다가 함수 실행 종료와 함께 동 시에 사라진다. javascript의 함수 실행되는 데 일조하는 친구들이다. arguments 속성은 함수의 지역 변수와 함께 scope chain에 들어가야 한다. 그래야만 함 수 중첩시에 적절한 arguments object에 접 근할 수 있다.

[administer the scope chain]
call object는 함수 실행 중에만 존재한다. call object는 scope chain에 아래 나열한 것 들을 가져다놓는다. 함수 내에 선언된 지역 변수 함수에 넘겨진 매개 변수 함수 표현을 도와주는 arguments object의 포인터, 우리가 알고 있는 바로 그 arguments! 위에 나열한 것들은 모두 call object의 속성 들이다. call object는 global object와 결합 되어 처리한다. 모든 전역 변수들은 global object의 속성이다. 페이지가 초기화될 때 global object는 전역 변수들을 scope chain 에 올린다. call object의 목적은 scope chain 에 전역 변수에 앞서 지역 변수를 올리는 것 이다. javascript는 전역 변수와 지역 변수가 이름이 같다고 해도 지역 변수에 전역 변수 가 덮어써지지 않도록 한다. 함수 중첩 시에 도 각 함수들은 나름의 call object를 가진다.

요약하자. 두 개의 함수가 같은 이름을 가지 고 있을 때 그 독립성은 유지된다. 하위 객체의 scope chain에 있는 변수는 상 위 객체의 같은 이름을 가진 변수로 덮어써 지지 않는다. 중첩 함수들은 나름의 call object를 통해 지 역 변수의 독립성을 보장받는다. 함수 안의 call object는 scope chain의 최상위에 존재 한다. call object가 scope chain에서 사라지면, 하 위 객체의 변수들은 해당 함수 실행 시에 적 절한 scope에서 다시 접근할 수 있다.

javascript는 함수 실행시에 아래 두 개의 객 체의 도움을 받는다. arguments object: 실행될 함수에 전달된 매 개변수들과 관련된 속성을 가짐 call object 이 두 객체는 함께 동작하며, 다음과 같은 일 반적인 특징을 가진다. javascript 함수를 지원한다. 임시적으로 존재한다. 함수가 실행될 때 만들어졌다가 함수가 종 료되면 사라진다. call object는 argumets object를 참조한다. 이 포인터는 call object의 속성이다. 이 포인터는 “arguments"라는 이름으로 식 별된다.

이 포인터는 argument object이 속성에 접 근시에 사용된다. 이 포인터는 함수 실행 시 함수 몸체에서 사 용할 수 있다.
[the call object description]
call object는 특별한 임시 객체로 함수가 실 행되는 동안 존재한다. call object는 두 가지 중요한 목적을 가진다. argument object를 가리키는 포인터를 제공 한다. 함수 실행 시 scope chain을 관장한다. call object는 이 외의 다른 속성이나 기능이 없다.
[the pointer to the arguments object]
call object는 argument object를 가리키는 포인터를 제공한다. 이 속성이 바로 arguments 속성이다. arguments 속성을 통 해 argument object의 속성에 접근할 수 있 다.

javascript는 왜 arguments 속성을 call object에 넣어두었을까? 이유는 다음과 같 다. arguments object는 native object가 아니기 때문에 인스턴스를 만드는 등, 끌어다 쓸 방 법이 없다. 즉, arguments object의 속성에 접근할 수 있는 방법이 없는거다. 그래서 call object에 arguments object를 가리키는 포인터(속성)을 제공하는 것이다. call object 와 arguments object는 함수 실행시에 동시 에 만들어졌다가 함수 실행 종료와 함께 동 시에 사라진다. javascript의 함수 실행되는 데 일조하는 친구들이다. arguments 속성은 함수의 지역 변수와 함께 scope chain에 들어가야 한다. 그래야만 함 수 중첩시에 적절한 arguments object에 접 근할 수 있다.

[administer the scope chain]
call object는 함수 실행 중에만 존재한다. call object는 scope chain에 아래 나열한 것 들을 가져다놓는다. 함수 내에 선언된 지역 변수 함수에 넘겨진 매개 변수 함수 표현을 도와주는 arguments object의 포인터, 우리가 알고 있는 바로 그 arguments! 위에 나열한 것들은 모두 call object의 속성 들이다. call object는 global object와 결합 되어 처리한다. 모든 전역 변수들은 global object의 속성이다. 페이지가 초기화될 때 global object는 전역 변수들을 scope chain 에 올린다. call object의 목적은 scope chain 에 전역 변수에 앞서 지역 변수를 올리는 것 이다. javascript는 전역 변수와 지역 변수가 이름이 같다고 해도 지역 변수에 전역 변수 가 덮어써지지 않도록 한다. 함수 중첩 시에 도 각 함수들은 나름의 call object를 가진다.

요약하자. 두 개의 함수가 같은 이름을 가지 고 있을 때 그 독립성은 유지된다. 하위 객체의 scope chain에 있는 변수는 상 위 객체의 같은 이름을 가진 변수로 덮어써 지지 않는다. 중첩 함수들은 나름의 call object를 통해 지 역 변수의 독립성을 보장받는다. 함수 안의 call object는 scope chain의 최상위에 존재 한다. call object가 scope chain에서 사라지면, 하 위 객체의 변수들은 해당 함수 실행 시에 적 절한 scope에서 다시 접근할 수 있다.