Javascript Trick 2 - Scope
TIL - Javascript 함수 스코프와 변수 탐색
문제 상황
아래 코드를 보면:
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo();
bar();예상: 10이 두 번 출력될 것이라고 생각했다.
실제 결과: 1이 두 번 출력되었다.
1
1코드 해석
1. 스코프(Scope)와 변수 탐색 규칙
- Javascript는 렉시컬 스코프(Lexical Scope) 기반 언어이다.
- 렉시컬 스코프란, “함수가 정의될 때” 결정된 스코프 체인을 따라 변수를 참조한다는 의미이다.
- 함수가 “어디서 호출되는가”가 아니라 “어디서 정의되었는가”가 중요하다.
2. 코드 동작 흐름
-
var x = 1;
\u2192 전역 변수x가 1로 설정된다. -
function foo() {...}
\u2192foo함수가 정의된다. 내부에x = 10을 선언하지만, 이는foo함수 내부에만 존재하는 지역 변수이다. -
function bar() {...}
\u2192bar함수가 정의된다.
bar함수 안에서는x를 찾을 때, 자신이 정의된 스코프(즉, 전역 스코프)를 기준으로 찾는다.
(bar함수는foo내부에서 정의된 것이 아님!) -
foo();호출
\u2192foo함수가 실행되면서var x = 10;이 생기고, 이어서bar();를 호출한다.
하지만bar는 전역 스코프에서 정의됐기 때문에, 여전히 전역 스코프를 참조한다.
전역x값은 여전히1이므로, 1이 출력된다. -
bar();호출
\u2192 이번엔 아예 전역 컨텍스트에서bar를 호출한다. 마찬가지로 전역x를 찾게 되므로 1이 또 출력된다.
예상과 실제의 차이 정리
| 예상 | 실제 |
|---|---|
foo 내부의 x = 10을 bar가 참조할 것이다. | bar는 정의된 스코프(전역)에서 x를 찾는다. |
| 호출 시점에 따라 스코프가 결정된다. | 정의 시점에 스코프가 결정된다. |
✅ Javascript에서는 “호출 시점”이 아니라 “정의 시점”에 스코프가 결정된다.
추가로 기억할 것
bar가foo안에서 정의되었다면, 결과가 달라졌을 것이다:
var x = 1;
function foo() {
var x = 10;
function bar() {
console.log(x);
}
bar();
}
foo();출력:
10
bar가 foo 내부에 정의되면, bar는 foo의 지역변수 x를 참조할 수 있게 된다.
한 문장 요약
Javascript의 스코프는 “함수 정의 시점”에 결정되며, 함수 호출 시점과는 무관하다.