Gitsunmin

TIL

TIL
(=Today I Learned)

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() {...}
    \u2192 foo 함수가 정의된다. 내부에 x = 10을 선언하지만, 이는 foo 함수 내부에만 존재하는 지역 변수이다.

  • function bar() {...}
    \u2192 bar 함수가 정의된다.
    bar 함수 안에서는 x를 찾을 때, 자신이 정의된 스코프(즉, 전역 스코프)를 기준으로 찾는다.
    (bar 함수는 foo 내부에서 정의된 것이 아님!)

  • foo(); 호출
    \u2192 foo 함수가 실행되면서 var x = 10;이 생기고, 이어서 bar();를 호출한다.
    하지만 bar는 전역 스코프에서 정의됐기 때문에, 여전히 전역 스코프를 참조한다.
    전역 x 값은 여전히 1이므로, 1이 출력된다.

  • bar(); 호출
    \u2192 이번엔 아예 전역 컨텍스트에서 bar를 호출한다. 마찬가지로 전역 x를 찾게 되므로 1이 또 출력된다.


예상과 실제의 차이 정리

예상실제
foo 내부의 x = 10bar가 참조할 것이다.bar는 정의된 스코프(전역)에서 x를 찾는다.
호출 시점에 따라 스코프가 결정된다.정의 시점에 스코프가 결정된다.

Javascript에서는 “호출 시점”이 아니라 “정의 시점”에 스코프가 결정된다.


추가로 기억할 것

  • barfoo 안에서 정의되었다면, 결과가 달라졌을 것이다:
var x = 1;
function foo() {
 var x = 10;
 function bar() {
   console.log(x);
 }
 bar();
}
foo();

출력:

10

barfoo 내부에 정의되면, barfoo의 지역변수 x를 참조할 수 있게 된다.


한 문장 요약

Javascript의 스코프는 “함수 정의 시점”에 결정되며, 함수 호출 시점과는 무관하다.