13.1 스코프란?
- 스코프(유효범위)는 변수, 함수에 깊은 관련이 있음
1. 스코프는 식별자가 유효한 범위 의미
➔ 모든 식별자는 (변수 이름. 함수 이름. 클래스 이름 등) 자신이 선언된 위치에 의해
다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정됨
var var1 = 1; // 코드의 가장 바깥 영역에서 선언한 변수
if (true) {
var var2 = 2; // 코드 블록 내에서 선언한 변수
if (true) {
var var3 = 3; // 중첩된 코드 블록 내에서 선언한 변수
}
}
function foo() {
var var4 = 4; // 함수 내에서 선언한 변수
function bar() {
var var5 = 5; // 중첩된 함수 내에서 선언한 변수
}
}
console.log(var1); // 1
console.Iog(var2); // 2
console.Iog(var3); // 3
console.log(var4); // ReferenceError: var4 is not defined
console.log(var5); // ReferenceError: var5 is not defined
2. 스코프는 식별자를 검색할 때 사용하는 규칙
➔ 자바스크립트 엔진은 이름이 같은 두 개의 변수 중에서 어떤 변수를 참조해야 할 것인지를 결정해야 하는데,
이를 식별자 결정(identifier resolution)이라고 함
➔ 자바스크립트 엔진은 코드를 실행할 때 코드의 문맥(context)을 고려하기 때문에 동일한 코드도 다른 결과를 만들어 냄
var x = 'global';
function foo() {
var x = 'local';
console.log(x); // local
}
foo();
console.log(x); // global
3. 스코프는 네임스페이스
➔ 스코프(유효 범위)를 통해 식별자인 변수 이름의 충돌을 방지하여같은 이름의 변수를 사용할 수 있게 함
➔ 스코프 내에서 식별자는 유일해야 하지만 다른 스코프에는 같은 이름의 식별자 사용 가능
(컴퓨터를 사용할 때 식별자인 파일 이름을 중복해서 사용할 수 이유는 폴더(디렉터리)라는 개념이 있기 때문, 이와 같은 맥락임)
13.2 스코프의 종류
- 코드는 전역(global)과 지역(local)으로 구분 가능
13.2.1 전역과 전역 스코프
- 전역 : 코드의 가장 바깥 영역
- 전역에 선언된 전역 변수는 어디서든지 참조 가능
13.2.1 지역과 지역 스코프
- 지역 : 함수 몸체 내부
- 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서 유효함
13.3 스코프 체인
- 중첩 함수 : 함수 몸체 내부에서 정의한 함수
- 외부 함수 : 중첩 함수를 포함하는 함수
➔ 함수 중첩 가능 = 스코프 중첩 가능
➔ 스코프가 함수의 중첩에 의해 계층적 구조 가짐
- outer 함수의 지역과 inner 함수의 지역이 존재
- inner 함수는 outer 함수의 중첩 함수
- outer 함수가 만든 지역 스코프는 inner 함수가 만든 지역 스코프의 상위 스코프
- outer 함수의 지역 스코프의 상위 스코프는 전역 스코프임
스코프 체인(scope chain) : 스코프가 계층적으로 연결된 것
└ 모든 스코프는 하나의 계층적 구조로 연결되며, 모든 지역 스코프의 최상위 스코프는 전역 스코프임
➔ 변수를 참조할 때, 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여, 상위 스코프 방향으로 이동하며 선언된 변수를 검색함(identifier resolution)
➔ 자바스크립트 엔진은 코드(전역 코드와 함수 코드)를 실행하기에 앞서 위 그림과 유사한 자료구조인 렉시컬 환경을 실제로 생성
*렉시컬 환경(Lexical Environment)
: 코드 block, function, script를 실행하기 앞서 생성되는 특별한 객체로, 실행할 스코프 범위 안에 있는 변수와 함수를 프로퍼티로 저장하는 객체
13.3.1 스코프 체인에 의한 변수 검색

위 그림의 4, 5, 6 참고
- ④ x 변수를 참조하는 코드의 스코프인 inner 함수의 지역 스코프에서 x 변수가 선언되었는지 검색
inner 함수 내에는 선언된 x 변수가 존재하기 때문에 검색된 변수를 참조하고 검색 종료
- ⑤ y 변수를 참조하는 코드의 스코프인 inner 함수의 지역 스코프에서 y 변수가 선언되었는지 검색
inner 함수 내에는 y 변수의 선언이 존재하지 않으므로 상위 스코프인 outer 함수의 지역 스코프로 이동
outer 함수 내에도 y 변수의 선언이 존재하지 않으므로 또 다시 상위 스코프인 전역 스코프로 이동
전역 스코프에는 y 변수의 선언이 존재하기 때문에 검색된 변수를 참조하고 검색 종료
- ⑥ z 변수를 참조하는 코드의 스코프인 inner 함수의 지역 스코프에서 z 변수가 선언되었는지 검색
inner 함수 내에는 z 변수의 선언이 존재하지 않으므로 상위 스코프인 outer 함수의 지역 스코프로 이동
outer 함수 내에는 z 변수의 선언이 존재하기 때문에 검색된 변수를 참조하고 검색 종료
자바스크립트 엔진은 스코프 체인을 따라 변수를 참조하는 코드의 스코프에서 시작해서 상위 스코프 방향으로 이동하며 선언된 변수를 검색➔ 상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조 가능
➔ 하위 스코프에서 유효한 변수를 상위 스코프에서 참조 불가능
13.3.2 스코프 체인에 의한 함수 검색
// 전역 함수
function foo() {
console.log('global function foo');
}
function bar() {
// 중첩 함수
function foo() {
console.log('local function foo');
}
foo(); // 'local function foo'
}
bar(); // 'local function foo'
// bar() 함수가 실행될 때마다 내부적으로 정의된 로컬 foo 함수가 호출되며,
// 전역 foo 함수는 이 코드 실행 동안에는 호출되지 않음
// 전체 코드 실행 과정에서 로컬 foo 함수만이 두 번 호출되어, 두 번 모두 'local function foo'가 출력
- 함수 선언문으로 함수 정의 시 런타임 이전에 함수 객체 생성 후, 자바스크립트 엔진에 의하여 함수 이름과 동일한 식별자에 할당됨
- 함수도 식별자에 할당되기 때문에 스코프를 가짐
- 함수 객체가 할당된 것 이외에는 일반 변수와 다를 바가 없기 때문에, 스코프는 식별자를 검색하는 규칙이라고 표현하는 것이 적합
13.4 함수 레벨 스코프
- 지역 : 함수 몸체 내부를 의미하며 지역은 지역 스코프를 만듦
- 코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성
블록 레벨 스코프(block level scope)
: C나 Java 등의 대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 코드 블록( if, for, while, try/catch 등)이 지역 스코프를 만듦
함수 레벨 스코프(function level scope)
: var 키워드로 선언된 변수는 오로지 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정
var x = 1;
if (true) {
// var 키워드로 선언된 변수는 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정
// 함수 밖에서 var 키워드로 선언된 변수는 코드 블록 내에서 선언되었다 할지라도 모두 전역 변수
// 따라서 x는 전역 변수
// 이미 선언된 전역 변수 x가 있으므로 x 변수는 중복 선언됨
// 이는 의도치 않게 변수 값이 변경돠는 부작용 발생
var x = 10;
}
console.log(x); // 10
└ if 문의 코드 블록 내에서 선언된 x는 전역 변수임
└ var 키워드로 선언된 변수는 함수 레벨 스코프만 인정하기 때문
var i = 10;
// for 문에서 선언한 i는 전역 변수
//이미 선언된 전역 변수 i가 있으므로 중복 선언
for (var i = 0; i < 5; i++) {
console.log(i); // 0 1 2 3 4
}
// 의도치 않게 변수의 값이 변경됨
console.log(i); // 5
└ var 키워드로 선언된 변수는 블록 레벨 스코프를 인정하지 않기 때문에 i 변수는 전역 변수
└ 따라서 전역 변수 i는 중복 선언되고 그 결과 의도치 않은 전역 변수의 값이 재할당됨
var 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하지만
ES6에서 도입된 let, const 키워드는 블록 레벨 스코프를 지원
13.5 렉시컬 스코프
-동적 스코프(dynamic scope) : 함수를 어디서 호출했는지에 따라 함수의 상위 스코프 결정
-렉시컬 스코프(lexical scope) : 함수를 어디서 정의했는지에 따라 함수의 상위 스코프 결정
➔ 자바스크립트는 렉시컬 스코프를 따름
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo(); // 1
bar(); // 1
└ bar 함수는 전역에서 정의된 함수
└ 함수 선언문으로 정의된 bar 함수는 전역 코드가 실행되기 전에 먼저 평가되어 함수 객체를 생성
└ 이때 생성된 bar 함수 객체는 자신이 정의된 스코프, 즉 전역 스코프 기억
└ 때문에 위 예제를 실행하면 전역 변수 x의 값 1을 두 번 출력
'🦎모던 자바스크립트 Deep Dive' 카테고리의 다른 글
[Chap 17] 생성자 함수에 의한 객체 생성 (0) | 2024.05.15 |
---|---|
[Chap 15] 스코프 (0) | 2024.05.07 |
[Chap 12] 함수 (0) | 2024.04.16 |
[Chap 11] 원시 값과 객체의 비교 (0) | 2024.04.10 |
[Chap 10] 객체 리터럴 (0) | 2024.04.10 |