[Javascript] 스코프 체인
JS 스코프 체인, JavaScript scope chain, JS scope
정의
스코프 체인 (Scope Chain) 은 변수 식별자를 해결할 때 따라가는 중첩된 Lexical Environment 의 연결 구조. 안쪽 스코프에서 찾지 못한 변수를 바깥 스코프로 차례로 검색.
시각화
global scope
└─ outer function scope
└─ inner function scope
└─ block scope { let x = 1 }
변수 lookup 은 inner → outer → global 순서.
기본 예
const a = 'global';
function outer() {
const b = 'outer';
function inner() {
const c = 'inner';
console.log(a, b, c); // 'global outer inner'
}
inner();
}
outer();
inner 에서 a 를 찾을 때:
inner스코프 → 없음outer스코프 → 없음global스코프 → ‘global’ 발견
정적 (Lexical) 스코프
JavaScript 는 lexical scope, 즉 함수가 정의된 위치 가 스코프를 결정. 호출 위치는 무관.
const x = 'global';
function foo() {
console.log(x); // 'global' (정의 위치 기준)
}
function bar() {
const x = 'local';
foo(); // 'global' (호출 위치 무관)
}
bar();
자세히는 Lexical Environment 참고.
블록 스코프 (ES6)
function foo() {
const x = 1;
if (true) {
const x = 2; // 새 블록 스코프
console.log(x); // 2
}
console.log(x); // 1
}
let/const 는 블록 단위, var 는 함수 단위.
클로저와의 관계
함수가 자기 정의 위치의 Lexical Environment 를 들고 다니는 것이 클로저.
function makeCounter() {
let count = 0;
return () => ++count;
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3
내부 화살표 함수가 makeCounter 의 LE 를 참조 → count 살아있음.
scope chain 의 lookup 순서
let x = 1;
function foo() {
let x = 2;
function bar() {
let x = 3;
console.log(x); // 3 (가장 가까운 정의)
}
bar();
}
foo();
가장 가까운 스코프부터 검색, 발견하면 즉시 사용 (shadowing).
global vs module 스코프
| 환경 | 최상위 스코프 |
|---|---|
| 브라우저 ES module | module 스코프 |
| 브라우저 일반 script | global 스코프 |
| Node.js CommonJS | module 스코프 |
| Node.js ES module | module 스코프 |
// ES module
const x = 1; // module 스코프
// window.x → undefined (global 에 attach 안 됨)
with 와 eval (피해야 할 것들)
with (obj) { ... } // 스코프 체인에 동적으로 obj 삽입
eval('var x = 1;') // 호출 스코프에 변수 삽입 (strict 모드 외)
둘 다 스코프 체인을 예측 불가능하게 만들어 최적화 방해. 사용 금지.
함정
1. 변수 호이스팅 + 스코프
let x = 1;
function foo() {
console.log(x); // ReferenceError (x 의 호이스팅된 TDZ)
let x = 2;
}
foo();
안쪽 let x 가 호이스팅되어 바깥 x 를 가림.
2. 클로저의 성능
모든 함수가 자기 LE 를 참조. 너무 많은 변수를 closure 로 가두면 메모리 압박. 진짜 불필요한 변수는 외부로.
3. global 오염
// 실수로 var 빼먹기 (sloppy 모드)
function foo() {
x = 1; // var/let/const 없이 → global 에 추가됨!
}
strict 모드에서는 ReferenceError. 항상 'use strict' 또는 ES module 사용.
참고
이 글의 용어 (4개)
- [Javascript] 클로저javascript
- 정의 클로저 (Closure): 함수가 자신이 정의된 시점의 외부 변수들을 계속 참조할 수 있는 성질. 함수가 일급 객체 () 인 언어의 자연스러운 결과. 메커니즘은 + 함수 객…
- [Javascript] 호이스팅 (Hoisting)javascript
- 정의 호이스팅 (Hoisting) 은 JavaScript 엔진이 코드 실행 전에 선언을 스코프의 최상단으로 끌어올리는 동작. 단, / 는 로 접근 제한. var 의 호이스팅 엔진…
- [Javascript] Lexical Environmentjavascript
- 정의 Lexical Environment (어휘적 환경) 는 ECMAScript 명세 (§9.1) 가 정의한 내부 객체. 함수가 호출될 때마다 새로 만들어지며, 이 호출의 변수들…
- [Javascript] var / let / constjavascript
- 정의 JavaScript 의 3 가지 변수 선언 키워드. | 키워드 | 스코프 | 재할당 | 재선언 | 호이스팅 | |:---|:---|:---:|:---:|:---| | | f…
💬 댓글