Notice
Recent Posts
Recent Comments
Link
«   2026/07   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

mimizae 님의 블로그

JavaScript의 Scope에 대해서 (3) 본문

JS

JavaScript의 Scope에 대해서 (3)

mimizae 2025. 11. 3. 22:15

 

lexical scope

lexical scope와 lexical environment는 실행 컨텍스트를 완벽 이해하기 위해 사전에 학습해야 할 내용이다. (lexical environment는 다음 글에서...)

 

우선 다음 예제의 실행 결과를 예측해 보는 것부터 시작하자.

var x = 1;
function foo(){
	var x = 10;
    bar();
}

function bar(){
	console.log(x);
}

foo(); //?
bar(); //?

 

// 호이스팅...
var x;
function foo(){
    var x;
    x = 10;
    bar();
}

function bar(){
	console.log(x);
}

x = 1;

foo(); //?
bar(); //?

 

위 예제의 실행 결과는 bar 함수의 상위 스코프가 무엇인지에 따라 결정된다.

이때 두 가지 패턴이 있는데, 각각의 패턴에 따라 결과가 달라진다.

 

1. 함수를 어디에서 호출했는지에 따라 함수의 상위 스코프를 결정한다.

2. 함수를 어디에서 정의했는지에 따라 함수의 상위 스코프를 결정한다.

 

1번 패턴으로 bar 함수의 상위 스코프를 결정한다면, foo 함수의 지역 스코프와 전역 스코프이다.

foo 내부에서 호출하고 전역에서 호출했기 때문이다.

 

2번 패턴으로 한다면 전역 스코프일 것이다. bar 함수가 정의된 곳이 전역이기 때문이다.

 

일반적으로 프로그래밍 언어는 두 가지 방식 중 한 가지를 선택해 함수의 상위 스코프를 결정하는데, 각각의 명칭이 다르다.

 

1. 동적 스코프

1번 패턴을 동적 스코프라고 한다. 함

수를 정의하는 시점에는 함수가 어디에서 호출될지 알 수 없다.

따라서 함수가 호출!!되는 시점에 동적으로 상위 스코프를 결정하기 때문에 동적 스코프라고 하는 것이다. (아하!)

 

2. 렉시컬 스코프 (정적 스코프)

2번 패턴을 렉시컬 스코프, 또는 정적 스코프라고 한다.

동적 스코프처럼  상위 스코프가 동적으로 변하지 않고 함수 정의가 평가되는 시점에 상위 스코프가 정적으로 결정되기 때문에 정적 스코프라고 부르는 것이다.

 

여기에서 주목할 점은, JS를 비롯한 대부분의 프로그래밍 언어가 렉시컬 스코프를 따른다는 것이다!

 

즉, JS는 렉시컬 스코프를 따르기에 함수가 어디에서 정의 되었는지가 함수의 상위 스코프를 결정하기에 함수가 호출된 위치는 아무런 영향도 주지 않는다.

 

즉!! 함수의 상위 스코프는 언제나, 자신이 정의된 스코프이다. (정의된 곳)

 

이처럼 함수의 상위 스코프는 함수 정의가 실행될 때 정적으로 결정된다.

함수 정의가 실행되어 생성된 함수 객체는 이렇게 결정된 상위 스코프를 기억한다. 

 

위 예제의 bar 함수는 전역에서 정의된 함수다.

함수 선언문으로 정의된 bar 함수는 전역 코드가 실행되기 전에 먼저 평가되어 함수 객체를 생성한다

(먼저 평가?;; 이 글을 읽고 실행 컨텍스트 글을 읽어보자.)

 

이때 생성된 bar 함수의 객체는 자신이 정의된 스코프, 즉 전역 스코프(=상위스코프)를 기억한다.

그리고 bar 함수가 호출되면 호출된 곳이 어디인지 관계없이 자신이 선언된 상위 스코프를 사용한다.

 

 

그럼 다시 렉시컬 스코프를 따른다는 것을 알았으니, 출력 결과를 제대로 예측해 보자.

 

var x;
function foo(){
    var x;
    x = 10;
    bar();
}

function bar(){
    console.log(x);
}

x = 1;

foo(); // 전역 변수의 1 출력 됨
bar(); // 전역 변수의 1 출력 됨

 

bar 함수는 전역에서 정의된 함수다. 함수 선언문으로 정의된 bar 함수는 전역 코드가 실행되기 전에 먼저 평가되어 함수 객체를 생성한다.

이때 생성된 bar 함수 객체는 자신이 정의된 스코프, 즉 전역 스코프를 기억한다.

 

그리고 bar 함수가 호출되면 호출된 곳이 어디인지에 관계없이 언제나 자신이 기억하고 있는 전역 스코프를 상위 스코프로 사용한다.

따라서 위 예제는 상위 스코프의 전역 변수 x에 할당된 값이 1이기 때문에 전역 변수 x의 값 1이 두 번 출력된다.

 

만약 지역 변수 x가 있다면...?

var x;
function foo(){
    var x;
    x = 10;
    bar();
}

function bar(){
    var x;
    x = 5; // 지역 변수 x가 있다면?
    console.log(x);
}

x = 1;

 

렉시컬 스코프는 선언된 위치로 상위 스코프를 정할 뿐, 내부의 지역 변수 우선 탐색 규칙은 그대로이므로

렉시컬 스코프를 따르는 규칙에 따라 bar 함수의 상위 스코프는 전역이지만, 출력되는 x 값은 지역 변수 x의 값 5일 것이다.

 

 


 

모던 자바스크립트 딥 다이브를 공부하고 쓴 글입니다!

'JS' 카테고리의 다른 글

this에 대해서  (0) 2025.11.11
실행 컨텍스트 보충 (전역 객체와 전역 코드 평가)  (0) 2025.11.09
실행 컨텍스트란?  (0) 2025.11.03
JavaScript의 Scope에 대해서 (2)  (0) 2025.10.26
JavaScript의 Scope에 대해서 (1)  (0) 2025.10.26