식별자(변수 이름, 함수 이름 등)가 유효한 범위를 스코프(scope
)라 한다.
var a = 'grape';
function fruit() {
var a = 'orange';
console.log(a);
}
fruit();
console.log(a);
[실행결과]
orange
grape
위 코드에서 바깥 영역과 fruit 함수 내부에 같은 이름을 갖는 a 변수를 선언했다. 바깥 영역의 a 변수는 어디서든 참조할 수 있으나, fruit 함수 내부의 a 변수는 함수 내부에서만 참조할 수 있다. 이때 두 개의 a 변수는 식별자 이름이 같지만 스코프(유효범위)가 다른 별개의 변수이다.
💡 var 키워드와 let, const 키워드로 선언한 변수의 중복 선언
var 키워드로 선언된 변수는 같은 스코프 내 중복 선언이 허용되므로 의도치 않은 변수값 변경이 발생할 수 있다.function fruit() { var a = 'lemon'; var a = 'cherry'; // 중복 선언 허용 console.log(a); } fruit(); [실행결과] cherry
let이나 const 키워드로 선언된 변수는 같은 스코프 내 중복 선언을 허용하지 않는다.
function fruit() { let a = 'lemon'; let a = 'cherry'; // SyntaxError, 중복 선언 허용 X } fruit();
코드의 가장 바깥 영역을 전역(global
)이라 하고 함수의 내부는 지역(local
)이라 한다.
전역은 전역 스코프(global scope
)를 만들고 변수를 선언하면 전역 변수(global variable
)가 된다. 전역 변수는 어디서든지 참조할 수 있다. 위 그림에서 'grape'를 할당한 a 변수가 이에 해당된다.
지역은 전역 스코프(local scope
)를 만들고 변수를 선언하면 전역 변수(local variable
)가 된다. 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서만 유효하다. 위 그림에서는 'orange'를 할당한 a 변수가 해당된다.
// scope chain
var x = 'bear';
var y = 'piglet';
function winnieThePooh() {
var z = 'tigger';
console.log(x); // bear
console.log(y); // piglet
console.log(z); // tigger
function hero() {
var x = 'pooh';
console.log(x); // pooh
console.log(z); // tigger
}
hero();
}
winnieThePooh();
console.log(x); // bear
위 코드는 전역 스코프와 winnieThePooh 지역 스코프, hero 지역 스코프가 존재한다. 모든 스코프는 하나의 계층적 구조로 연결되는데, 이를 스코프 체인(scope chain
)이라 부른다.
변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하면서 선언된 변수를 검색한다. 때문에 하위 스코프에서 상위 스코프의 변수를 참조할 수 있다.
var 키워드로 선언된 변수는 함수의 코드 블록만을 지역 스코프로 인정하는데, 이를 함수 레벨 스코프(function level scope
)라 한다.
// function level scope
var one = 1;
if (true) {
var one = 2;
}
console.log(one);
[실행결과]
2
var 키워드로 선언된 변수 one은 코드 블록 내에서 선언되었다 할지라도 함수의 코드 블록이 아니라면 전역 변수이다. 때문에 if 문 내의 변수 one은 중복 선언이 된다. 이는 의도치 않게 변수 값이 변경되는 부작용을 발생시킨다.