스코프는 식별자의 유효 범위를 의미하며, JS
는 전역
과 함수
단위로 스코프를 생성한다.
var a = "global scope";
function func() {
var b = "function scope";
if (true) {
var c = "function scope 2";
}
console.log(c);
console.log(a);
}
console.log(a);
func();
console.log(b);
/* result
global scope
function scope 2
global scope
ReferenceError: b is not defined
*/
a
는 전역에 선언되었으므로 어디서든 호출할 수 있다.
b
와 c
는 함수 내부에서 선언되어, 함수 밖에서 호출하면 에러가 발생한다. 여기서 c
는 if
블록 안에서 선언되었지만, var
의 특성으로 인해 함수 스코프에 정의된다. 따라서 func
함수 내 어디서든 c
에 접근할 수 있다.
스코프의 범위가 구분되기 때문에 변수를 재선언하더라도 다른 결과값을 출력한다.
var x = "global";
function foo() {
var x = "local";
console.log(x);
}
foo();
console.log(x);
/* result
local
global
*/
함수가 아닌 코드 블록에서 var
는 문제가 될 수 있다.
var foo = "foo";
if (true) {
var foo = "bar";
}
console.log(foo);
var foo
가 if
블록 내에 재선언되었지만, 함수 스코프가 아니기 때문에 모든 var foo
는 전역 스코프에 속한다. var
식별자는 함수 블록만을 인정한다. 이는 for
문에서 var
를 선언했을 때도 문제가 된다.
var i = 10;
for (var i = 0; i < 5; i++) {
console.log(i); // 0 1 2 3 4
}
console.log(i); // 5
var
로 선언한 i
는 모두 전역 변수가 되고, 재할당되어 의도치 않은 결과를 출력되었다.
JS
는 렉시컬 스코프
를 따르는 언어다. 함수를 어디서 호출했는지가 아닌 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다.
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo();
bar();
/* result
1
1
*/
foo
와 bar
모두 정의한 곳은 전역이므로, 둘 다 전역 스코프를 상위 스코프로 기억한다. foo
안에서 bar
를 호출한 것과 관계없이 전역 변수 var x = 1
을 두 번 출력한다.
참고
『초보자를 위한 자바스크립트 200제』, 고재도, 노지연, 정보 문화사, p.116~118
『모던 자바스크립트 Deep Dive』, 이웅모, 위키북스, p.189~199