모든 식별자(변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위. 즉, 식별자가 유효한 범위 입니다.
var x = 'global';
function foo(){
var x = 'local';
console.log(x);
}
foo();
console.log(x);
코드의 가장 바깥 부분 - 전역 변수
함수 몸체 내부 - 지역변수
모든 스코프는 계층 구조로 연결되고 최상위 스코프는 전역 스코프가 됩니다. 변수를 참조할 때 자바스크립트 엔진은 스코프체인을 통해 변수를 참조하는 스코프부터 상위 스코프 방향으로 이동하며 선언된 변수를 찾습니다.
var x = 'global x';
var y = 'global y';
function outer(){
var z = 'outer local z'
console.log(x);
console.log(y);
console.log(z);
function inner(){
var x = 'inner local x';
console.log(x);
console.log(y);
console.log(z);
}
}
outer();
console.log(x);
console.log(z);
하위에서는 상위 스코프를 자유롭게 참조할 수 있지만 상위에서 하위 변수를 참조할 수는 없습니다. 마치 상속처럼요.
코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성됩니다. 코드 블록(if, for, while)이 만드는 지역 스코프를 블록 레벨 스코프라고 합니다. 하지만 var
로 선언된 변수는 함수 레벨 스코프(함수 몸체)만을 지역 스코프로 인정합니다.
var x = 1;
if(true){
var x = 10;
}
console.log(x);
아래 코드에서 bar
함수의 상위 스코프가 무엇일지 생각해봅시다.
var x = 1;
function foo(){
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo();
bar();
자바스크립트는 렉시컬 스코프를 따르기 때문에 함수를 어디서 정의 했는지에 따라 상위 스코프를 결정합니다. 함수의 상위 스코프는 정의가 실행될 때 정적으로 결정됩니다. 그래서 함수 정의가 실행되어 생성된 함수 객체는 존재하는 동안 결정된 상위 스코프를 기억합니다.
function makeCounter() {
let count = 0; // this is a local variable in the makeCounter function's scope
return function() { // the returned function is created within the scope of makeCounter
return count++; // so it has access to the count variable
};
}
let counter1 = makeCounter();
let counter2 = makeCounter();
console.log(counter1()); // 0
console.log(counter1()); // 1
console.log(counter2()); // 0
console.log(counter1()); // 2