스코프란, 모든 식별자는 자신이 선언된 위치에 따라 식별자 자신을 참조 가능한 유효 범위를 갖는데 이를 스코프라한다.
식별자는 어떤 값을 구별할 수 있는 유일성을 가져야한다. 따라서 식별자는 중복될 수 없다.
하지만 같은 식별자이지만 다른 스코프를 가진다고 하면 중복이 가능하다.(=식별자 유효 범위가 다르기 때문에 가능)
자바스크립트 검색 엔진은 스코프를 기준으로 참조할 변수를 찾는다.
var x = "global";
function foo() {
var x = "local";
console.log(x); // local
}
foo();
console.log(x); //global
위 코드에서 "x"변수는 2번 사용되었다. 하지만 선언된 위치에 따라
global값을 가진 x는 전역 스코프를 갖고
local값을 가진 x는 지역 스코프를 갖기때문에
syntax Error 와 Reference Error가 발생하지 않는다.
코드의 가장 바깥 영역으로 코드 어디에서든지 참조할 수 있다.
전역에서 선언된 변수이며 전역 스코프를 가지기 때문에 어디에든 참조할 수 있다.
지역이란, 함수 내부를 뜻한다.
함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.
지역(함수) 내에서 선언된 변수이며 지역 스코프를 가지기 때문에 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.
아래 스코프 이미지에 대한 설명:
1번은 inner스코프에 x변수는 없지만 스코프 체인에 따라 상위 스코프인 outer스코프에 있는 x를 참조한다.
2번은 inner스코프의 y변수를 참조한다.
3번은 outer스코프의 x변수를 참조한다.
4번은 전역 변수x를 참조한다.
5번은 전역 스코프에 y변수가 없기 때문에 ReferenceError가 발생한다.
함수를 정의하는데 있어 함수 안에 또 다른 함수가 정의 될 수 있다.
이러한 현상을 함수의 중첩이라 한다.
함수의 중첩은 외부함수(outer func)와 중첩된 함수(nested func)로 나누어 지는데,
위의 예제에서 outer함수를 외부함수라하고 inner함수를 중첩된 함수라 한다.
이러한 중첩된 관계를 가진 함수들이 생기면 지역 스코프도 중첩된 관계를 가지게 된다.
이러한 관계를 스코프에서 스코프 체인이라 부른다.
외부 함수 스코프를 상위 스코프라 부르고 중첩 함수 스코프를 하위 스코프라 부른다.
하위 스코프에서 상위 스코프로 참조가 가능하고 역으로 상위 스코프에서 하위 스코프로의 참조는 불가하다.
변수가 사용된 스코프 내에서 해당 변수를 참조할 수 없는 경우 스코프 체인을 따라 상위 스코프로 한단계 올라가서 찾게된다.
모든 코드 블록(if, while, for, func, ...등'{...}'으로 감싸진 영역)이 지역 스코프를 가지게 되는데 이러한 스코프를 블록 레벨 스코프라한다.
하지만 var로 선언된 변수는 오직 함수 코드 블록만 지역 스코프를 가진다.
var i = 5;
// for문 조건식 변수 i는 함수 레벨 스코프인 var로 중복 선언되었기 때문에 전역 변수가 된다.
for (var i = 0; i < 3; i++) {
console.log(i); // 0 1 2
}
// for문 내 console.log(i)는 i=2일때 조건식(i<3)을 만족시켜
// 2 값이 출력된 다음에 i값을 증가시키므로 전역 변수 i의 값이 5가 아닌 3으로 재할당된다.
console.log(i); // 3
함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
자바스크립트는 다른 언어와는 다르게 렉시컬 스코프를 따른다.
함수가 선언(정의)된 위치에 따라 상위 스코프가 정해지는데 이러한 방식을 렉시컬 스코프라한다.
함수가 호출된 위치가 아닌 선언된 위치를 기준으로 이미 정해저 있기때문에 정적 스코프로 불리기도 한다.
var x = 1;
function foo() {
var x = 10;
console.log(x); // result:10 1번
bar();
}
function bar() {
console.log(x);
}
foo(); // result:1 2번
bar(); // result:1 3번
1번. foo함수 정의 위치는 전역스코프이지만
foo함수 내 var x는 함수 레벨 스코프이므로 foo함수 내 지역 스코프를 가진다.
따라서 var x=10을 참조한다.
2번. 함수foo 지역 스코프에 있는 함수bar는 정의된 위치가 전역 스코프이다.
따라서 foo 내 bar가 호출 시 전역 변수 x=1을 참조한다.
3번. bar함수 정의 위치가 전역 스코프이기 때문에 전역 변수 x=1를 참조한다.