스코프(Scope)
개요
스코프는 변수에 접근할 수 있는 범위를 말한다. JavaScript에서 변수를 선언하면 그 변수는 특정 스코프에 속하게 되고, 해당 스코프 내에서만 접근할 수 있다. 스코프를 이해하면 변수가 언제 생성되고, 어디서 접근 가능하며, 언제 사라지는지 알 수 있다.
전역 스코프 (Global Scope)
함수나 블록 외부에서 선언된 변수는 전역 스코프에 속한다. 어디서든 접근할 수 있다.
const globalVar = "나는 전역 변수";
function foo() {
console.log(globalVar); // 접근 가능
}
if (true) {
console.log(globalVar); // 접근 가능
}
전역 변수는 편리하지만, 어디서든 수정될 수 있어서 예측하기 어려운 버그를 만들 수 있다. 가능하면 사용을 최소화하는 것이 좋다.
함수 스코프 (Function Scope)
var로 선언된 변수는 함수 스코프를 가진다. 함수 내부에서 선언하면 그 함수 안에서만 접근할 수 있다.
function foo() {
var functionVar = "나는 함수 스코프 변수";
console.log(functionVar); // 접근 가능
}
foo();
console.log(functionVar); // ReferenceError: functionVar is not defined
함수가 끝나면 함수 스코프의 변수는 사라진다.
var의 특이한 동작
var는 블록을 무시한다:
function foo() {
if (true) {
var x = 10;
}
console.log(x); // 10 - 블록 밖에서도 접근 가능!
}
if 블록 안에서 선언했지만, var는 함수 스코프이므로 함수 전체에서 접근할 수 있다. 이런 동작이 혼란을 주기 때문에 현대 JavaScript에서는 let과 const를 권장한다.
블록 스코프 (Block Scope)
let과 const로 선언된 변수는 블록 스코프를 가진다. 블록({})은 if문, for문, while문 등에서 사용하는 중괄호를 말한다.
if (true) {
let blockVar = "나는 블록 스코프 변수";
const blockConst = "나도 블록 스코프";
console.log(blockVar); // 접근 가능
}
console.log(blockVar); // ReferenceError: blockVar is not defined
블록이 끝나면 해당 블록 스코프의 변수는 사라진다.
for문에서의 차이
// var - 함수 스코프
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 출력: 3, 3, 3
// let - 블록 스코프
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100);
}
// 출력: 0, 1, 2
var는 함수 스코프라서 루프가 끝난 후의 i 값(3)을 참조한다. let은 각 반복마다 새로운 블록 스코프를 만들어서 해당 시점의 값을 유지한다.
렉시컬 스코프 (Lexical Scope)
JavaScript는 렉시컬 스코프(정적 스코프)를 사용한다. 함수가 어디서 호출되었는지가 아니라 어디서 정의되었는지에 따라 상위 스코프가 결정된다.
const x = 10;
function foo() {
console.log(x);
}
function bar() {
const x = 20;
foo();
}
bar(); // 10 - foo가 정의된 곳의 x를 참조
foo()가 bar() 안에서 호출되었지만, foo()가 정의된 곳은 전역이므로 전역의 x(10)를 참조한다.
스코프 체인 (Scope Chain)
변수를 찾을 때 현재 스코프에 없으면 상위 스코프를 차례로 탐색한다. 이를 스코프 체인이라 한다.
const a = 1;
function outer() {
const b = 2;
function inner() {
const c = 3;
console.log(a, b, c); // 1, 2, 3 - 모두 접근 가능
}
inner();
}
outer();
inner 함수에서:
c→ 현재 스코프에서 발견b→ 상위 스코프(outer)에서 발견a→ 더 상위 스코프(전역)에서 발견
전역까지 탐색해도 없으면 ReferenceError가 발생한다.
요약
| 스코프 | 키워드 | 범위 |
|---|---|---|
| 전역 | var, let, const (함수/블록 밖) | 어디서든 접근 가능 |
| 함수 | var | 함수 내부에서만 접근 가능 |
| 블록 | let, const | 블록 내부에서만 접근 가능 |
var는 함수 스코프,let/const는 블록 스코프- JavaScript는 렉시컬 스코프(정의 위치 기준)
- 변수 탐색은 스코프 체인을 따라 상위로 이동