스코프체인
==================================
소개
이전글에서 소개한 function에 대한 글의 연속으로 이번글에서는 function 이 가진 여러가지 특성들에 대하여 알아보려고 한다. 이번 글에서 소개하는 function 의 특성은 Scope, Scope Chain 그리고 arguments 객체 이다. 이들은 Execution Context라는 개념에서 함수객체가 만들어지면서 생성되는 것들로서 이글 이후에 소개될 Execution Context에 대한 이해를 위해 필요로하는 녀석들이다. 그러므로 이번글에서 소개되는 내용을 통해 Scope, Scope Chain, arguments 에 대한 기본적인 이해에 도움이 되었으면 한다.
함수(function)의 특징
함수는 전역변수와 지역변수를 활용할 수 있다.
함수는 자신의 statement 안에서 변수를 선언하여 지역변수로 사용할 수 있다.
이때 선언된 지역변수는 해당 함수안에서만 접근가능한 private variable 이 된다. 즉 함수 코드블럭을 벗어나게 되면 해당 변수는 메모리에서 사라지게 된다.
function foo() {
var x= 1; // 함수안에서 선언된 변수임에 지역변수이다.
return x;
}
console.log(foo());
1
console.log(x); // 외부에서 참조할수 없다.
undefined
하지만 global 영역에 선언된 전역변수는 자바스크립트 코드 어디에서든 사용할 수 있기에 함수안에서도 전역변수를 이용할 수 있다
var x= 1; // global 영역에 선언된 전역변수
function foo() {
return x; // 전역변수 x를 return
}
console.log(foo());
1
console.log(x); // 어디서든 참조가능한 전역변수
1
함수에서 전역변수와 지역변수사용함에 있어 재미있는 현상이 하나 있다. 바로 중첩된 이름의 변수 사용이다. 자바스크립트는 global 영역에 선언된 변수와 동일한 이름의 지역변수를 사용할수 있다. 이로 인해 디버깅 과정중에 많은 혼란을 초래하기도 한다.
var x='hello'; // 전역변수 x 에 hello 할당.
function foo() {
var x='world'; // 지역변수 x 에 world할당.
return x;
}
console.log(foo());
world // 함수실행에 따라 지역변수 x에 할당된 world 가 출력된다.
console.log(x);
hello // 전역변수 x에 할당된 hello 가 출력된다.
전역변수와 지역변수를 동일한 이름으로 사용했을경우 지역변수에서 다른 값을 할당하여도 전역변수에는 아무런 변화가 없다.
즉 전역변수와 지역변수를 동일한 이름으로 사용하여도 각각 다른 변수객체가 만들어진다는 것을 알수 있다. 이 현상에 대해 정확히 이해하기 위해서는 Scope 와 Scope Chain 이란 녀석들에 대해 이해하고 있어야 한다.
함수객체의 Scope & Scope Chain
Scope & Scope Chain
ECMA-262 3 Edition 에서는 함수객체는 [[scope]] 라는 프로퍼티를 가지며 [[scope]]는 함수객체가 생성되는 시점과 관련된 Object Reference 정보를 가지고 있으며 이 Object Reference 정보들을 Scope Chain 이라고 한다고 정의한다. 즉 scope는 함수객체가 접근가능한 Valiable Object의 유효범위이며 이 Valiable Object들의 집함을 Scope Chain 이라고 한다.
함수객체는 생성과정에서 함수구문 내에서 선언된 지역변수들을 Valiable Object 라는 객체에 저장한다. 그리고 전역객체(Global Object)의 Valiable Object 와 연결된다. 전역객체의 Valiable Object는 전역객체 자신이다. 이때 이 Valiable Object들에 대한 연결들을 Scope Chain 으로 관리하고 [[scope]]를 통해 Scope Chain을 참조하여 함수객체가 가지는 유효범위를 설정하게 되는 것이다.
var x = 1;
function foo() {
var y = 10;
return a+x;
}
console.log(z);
ReferenceError;
위 예제코드의 foo() 함수객체가 생성될 때의 [[Scope]]와 Scope Chain 에 대한 연결은 아래 다이어그램을 보면 쉽게 이해할수 있다.

변수의 검색은 이 Scope Chain 에서만 탐색 된다. Scope Chain의 하위에서부터 상위로 등록된 변수가 있는지 찾아가며 가장 처음 탐색되는 scope에 등록된 변수를 이용한다. 즉 Scope Chain 에의해 탐색되지 않는 변수는 undefined 이며 그런 이유로 예제의 console.log(z); 는 foo함수가 가진 유효범위에서 찾을 수 없는 변수 z 에 대한 접근을 하기 때문에 ReferenceError 가 되는 것이다. 처음의 의문으로 돌아가서 전역변수 x와 지역변수 x가 동일한 이름으로 사용이 가능한 이유는 이처럼 각각 x에 접근하기 위해 참조하는 Valiable Object가 다르기 때문인 것이다.