상세 컨텐츠

본문 제목

[JavaScript] 스코프 체인

개발공부/JavaScript

by 임우찬 2019. 9. 11. 11:03

본문

 

1. 스코프 체인이란?

- 실행컨텍스트 내용에서 스코프 정보에 대한 이야기를 했었다.

- 대강 다시 설명하자면, 실행 컨텍스트가 생성되면 js엔진은 해당 컨텍스트에서 실행에 필요한 여러가지 정보를 담은 "활성객체"라는 객체를 생성하는데, 이 활성 객체에 함수의 인자들을 유사 배열 형태로 담는 arguments라는 객체가 생성되고, 현재 컨텍스트의 유효범위를 나타내는 스코프 정보를 생성, 이후 변수생성과 this 바인딩을 한다고 하였다.

- 스코프 정보는 현재 실행중인 실행 컨텍스트 안에서 연결 리스트와 유사한 형식으로 만들어진다 하였는데, 이 리스트를 "스코프 체인"이라고 한다 하였다. [[scope]] 프로퍼티로 참조된다.

- 다시 설명하자면, 유효 범위를 나타내는 스코프가 [[scope]] 프로퍼티로 각 함수 객체 내에서 연결리스트 형식으로 관리되는데, 이 스코프간의 상하관계를 "스코프 체인"이라고 한다는 것이다.

- 그렇다면 변수의 스코프란? 이라는 질문은 무엇을 묻는 질문일까?

이는 선언된 변수가 어느 위치에서 유효한가를 묻는다고 보면 된다.


2. 전역 실행 컨텍스트의 스코프 체인

예시)

var var1 = 1;
var var2 = 2;
console.log(var1);
console.log(var2);

- 위 코드 실행시 먼저 전역 실행 컨텍스트로 생성이 되고, 변수 객체(활성 객체)가 만들어진다.

* (여기서 말하는 변수객체와 활성 객체는 같은 것을 의미한다.)

- 이 변수 객체(활성 객체)의 스코프 체인은 자신이 최상위에 위치하는 변수 객체(활성 객체)이기에, 자기 자신만을 가진다.

- 다시 말해, 변수 객체의 [[scope]]는 변수 객체 자신을 가리키는 것이다.

- 그 후, var1,var2 변수들이 생성되고 변수 객체에 의해 참조된다.

위 코드를 그림으로 나타낸 것이다.


- 스코프 체인을 다시 이야기하면, 자바스크립트도 다른 언어와 마찬가지로 스코프, 즉 유효범위가 있다. 이 유효범위 안에서 변수와 함수가 존재하는 것이다.

- 예를 들어 {}로 묶어있는 범위 안에서 선언된 변수는 블록이 끝나는 순간 사라지므로, 밖에서는 접근이 불가능하다. 그러나 자바스크립트에서는 "오직 함수만이" 유효범위의 한 단위가 되는 것이다.

- 따라서 스코프란 변수의 접근 가능 범위를 뜻하는 말이고, 스코프 간의 상하관계를 스코프 체인이라 부르는 것이다.

 


3. 스코프 체인 예시(2)

var value = "value1";
function printFunc(){
var value = "value2";
function printValue(){
return value;
}
console.log(printValue());
}
printFunc();

다음과 같은 코드가 있다고 가정하자.이럴 경우 그림으로 표현하게 된다면

이와 같은 형태로 실행된다.

 


4. 스코프 체인 예시 (3)

var value = "value1";
function printValue(){
return value;
}
function printFunc(Func){
var value = "value2";
console.log(func());
}
printFunc(printValue);

- 함수 객체가 처음 생성될 당시 실행 컨텍스트가 무엇인지 생각하는 것이 중요하다.

("불러올 함수가 어느 실행 컨텍스트에 위치한가?")

- 각 함수 객체가 처음 생성될 때 [[scope]]는 전역 객체의 [[scope]]를 참조한다.

- 따라서 함수 실행 시 생성되는 실행 컨텍스트의 스코프 체인은 전역 객체와 그 앞에 새롭게 만들어진 변수 객체가 추가된다.


5. 식별자 인식

- 스코프 체인으로 식별자 인식이 이루어진다.

- 식별자 인식은 스코프 체인의 첫 번째 변수 객체부터 시작한다.

(식별자와 대응되는 이름을 가진 프로퍼티가 있는가?)

- 스코프 체인의 가장 앞에 있는 객체가 변수 객체이므로, 이 객체에 있는 공식 인자, 내부함수, 지역변수에 대응되는지 먼저 확인한다.

- 첫 번째 객체에서 대응되는 프로퍼티를 발견하지 못할 경우 대음 객체로 이동하게 되는데, 이는 찾을 때 까지 계속해서 내려가게 된다.

- this 는 식별자가 아닌 "키워드"로 분류되기 때문에, 스코프 체인의 참조 없이 접근이 가능하다.


6. 클로저

예시)

function outerFunc(){
var x = 10;
var innerFunc = function() { console.log(x);}
return innerFunc;
}
var inner = outerFunc();
inner(); //10

- 이 내용을 앞의 내용처럼 스코프 체인을 그려본다면 다음과 같다.

- innerFunc()의 [[scope]]은 outerFunc 변수 객체와 전역 객체를 가진다.

- 그런데 여기서 보면 innerFunc()은 outerFunc()이 끝난 뒤 실행된다.

- 그렇다면 outerFunc 실행 컨텍스트가 사라진 이후에 innerFunc 실행 컨텍스트가 생성되는 것이라 생각할 수 있다.

- 그러나 outerFunc 실행 컨텍스트가 사라졌더라도, outerFunc변수 객체는 여전히 남아있고, innerFunc의 스코프 체인으로 참조되고 있다.

- 이것이 자바스크립트에서 구현한 클로저라는 개념이다.

- 간단하게 이미 생명주기가 끝난 외부함수의 변수를 참조하는 것을 클로저라고 하는데, 이 때 클로저에 참조되는 외부변수를 "자유변수"라고 한다.

- closure 라는 이름은 함수가 자유변수에 닫혀있다는 의미로, "자유변수에 엮여있는 함수"라고 이해하면 된다.

관련글 더보기

댓글 영역