Front-end Developer

0%

스코프 실습

다음과 같은 중첩함수가 있을 때, console.log에는 어떤 값이 출력될까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function outer() {
let x = 3;
// 중첩 함수
function inner() {
let y = 2;
// 외부 함수의 변수를 참조할 수 있다.
console.log(x + y);
}

return inner;
}

const content = outer();
content();

outer 함수는 변수 content의 이름으로 할당되었는데, 이 함수가 반환하는 값은 let x = 3이 아니라 inner이다. outer 내부의 inner 함수가 return값으로 설정되어 있기 때문이다. 따라서 inner 함수내부에서 실행한 x+y의 값인 5가 콘솔에 출력된다.

그런데 의아한 부분이 있다.

inner 함수 내부에는 let y = 2의 y값만 할당되어 있고, x값은 할당되어 있지 않다. 그런데 어떻게 두 값이 x+y로 연산되어 출력된 것일까?

가장 먼저 생성된 outer 함수가 호출되면 이 함수는 stack의 가장 아래에 쌓인다. (stack 가장 마지막에 들어온 것이 가장 먼저 나가는 구조이다.)
그 다음 inner 함수를 호출하면 이 함수는 outer의 위에 쌓인다. 그런데 변수 content에 outer 함수를 호출했을 때 반환하는 값은 inner 함수이다. 결국 content = inner 함수가 되는 셈이다.

그래서 실행 컨텍스트에 따라 inner함수를 살펴본다. inner 함수 내부에는 콘솔에 x+y의 값이 찍히도록 되어 있지만 y의 값만 존재한다. 그럼 이 함수는 바로 상위로 향하여 x값이 존재하는지를 살펴본다. 만약 존재한다면 그 값을 참조하여 x + y의 값을 출력한다. 하지만 만약 여기서도 x값이 존재하지 않는다면 그보다 상위 개념에 x값이 존재하는지를 살펴보았을 것이다. 이처럼 자바스크립트의 스코프는 함수의 중첩에 따라 계층적 구조를 가지기 때문에 하위 스코프인 inner 함수에 필요로 하는 식별자가 없다면 그보다 상위 스코프이자 outer environment인 outer 함수에 식별자가 있는지 확인하고 있다면 그 값을 참조한다.

그리고 모든 스코프의 가장 최상위에는 전역 스코프가 존재한다.

그렇다면, 전역 스코프에 변수가 할당되어 있다면 어떻게 될까?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let x = 1;
function outer() {
let x = 3;
// 중첩 함수
function inner() {
let y = 2;
// 외부 함수의 변수를 참조할 수 있다.
console.log(x + y);
}

return inner;
}

const content = outer();
content();

outer 함수의 상위인 전역 스코프에 let x = 1이라는 값이 할당되어 있다. 이때 x+y의 값은 콘솔에 어떻게 출력될까? stack의 구조와 상위 구조로 가면서 변수 식별자를 찾는 것에 따라 x + y의 값은 이제 1 + 3을 한 4라는 값이 찍힐까?

이 경우에는 함수가 한 번 호출되어 실행 컨텍스트를 한 번 돌아서 종료되면 stack에 저장되어 있는 값은 사라진다는 개념을 알아야한다. (해제된다는 개념이 더 정확할 것이다.) 만약 let x = 1;이 전역 스코프로 작성되고, outer 함수 내부에는 변수 x에 대한 할당이 따로 없었다면 3이라는 결과가 출력되었을 것이다.