자바스크립트에서 스코프는 변수나 표현식이 바인딩(visible) 되어있거나 참조 가능한 문맥을 뜻 합니다.
아래 예제를 보겠습니다.
function add(x,y) {
// 매개변수는 함수 몸체 내부에서만 참조할 수 있다.
// 즉, 매개변수의 스코프(유호범위)는 함수 몸체 내부다.
console.log(x, y)
return x+y;
}
add(2,5)
// 매개변수는 함수 몸체 내부에서만 참조할 수 있다.
console.log(x, y) // ReferenceError: x is not defined
매개변수 x,y는 함수 add 내부에서는 참조가 가능하나 add 외부에서는 참조가 불가능한 것을 확인할 수 있습니다. 그 이유는 변수 x,y는 함수 add의 스코프에 등록이 되어있어 함수 add 내부에서만 참조할 수 있기 때문입니다.
모든 식별자(변수, 함수, 클래스 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정됩니다. 이를 스코프라고 합니다. 즉, 스코프는 식별자가 유효한 범위를 말합니다.
스코프 체인은 스코프 가 계층적(hierarchy)으로 연결된 것을 의미합니다. 자바스크립트 엔진은 스코프 체인을 이용하여 식별자를 검색(retrieve) 합니다.
아래 예제를 보겠습니다.
var x = 'global x'
var y = 'global y'
function outer() {
var z = "outer's local z";
console.log(x); // global x
console.log(y); // global y
console.log(z); // outer's local z
function inner() {
var x = "inner's local x"
console.log(x); // inner's local x
console.log(y); // global y
console.log(z); // outer's local z
}
inner();
}
outer();
console.log(x); // global x
copsole.log(z); // ReferenceError : z is not defined
각각 변수가 포함되어있는 스코프는 아래와 같습니다.
위의 예제에서 함수 inner 내부의 값 y, z는 함수 inner 내부에 정의되어 있지 않습니다. inner 지역 스코프에 변수가 없기 때문에 스코프 체인을 통해서 상위 스코프를 탐색하여 해당 값을 찾게 됩니다.
자바스크립트 엔진은 평가 과정과 실행 과정을 가지고 있다는 것을 기억하시고 예제를 보시기 바랍니다.
위의 예제의 경우, 자바스크립트 엔진은 아래와 같이 동작합니다.
- 전역 실행 컨텍스트 생성
- 전역 실행 컨텍스트의 변수 x,y, 함수 outer가 바인딩 되어있는 스코프가 등록
- 평가 과정이 끝나 실행 과정이 시작
- 함수 outer를 만나 함수 outer에 대한 평가 과정과 실행 과정을 동작
- 함수 outer의 실행 컨텍스트 생성
- 함수 outer 실행 컨텍스트의 변수 z, 함수 inner가 바인딩 되어있는 스코프가 등록
- 함수 outer의 상위 스코프로 전역 실행 컨텍스트의 스코프가 등록
- .....
상위 스코프는 함수를 어디서 정의했는지에 따라서 결정이 됩니다.
아래 예제를 보겠습니다
var x = 1;
function foo() {
var x = 10;
bar();
}
function bar() {
console.log(x);
}
foo();
bar();
상위 스코프를 결정하는 방법을 2가지로 나눌 수 있습니다.
- 함수를 어디서 호출했는지에 따라서 결정
- 함수를 어디서 정의했는지에 따라서 결정
1번의 경우 foo()는 10을 출력, bar()는 1를 출력할 것 입니다. 이러한 방식을 동적 스코프라고 합니다.
2번의 경우 foo(), bar()는 1를 출력할 것 입니다. 이런한 방식을 렉시컬 스코프(lexical scope) 또는 정적 스코프(static scope)라 합니다.
자바스크립트는 2번의 경우를 따릅니다. 즉, 자바스크립트는 렉시컬 스코프를 따르므로 함수를 어디서 정의했는지에 따라서 상위 스코프가 결정 됩니다.
성능 상의 이점과 가독성을 위해서 스코프는 항상 최대한 좁혀서 코딩을 해야 합니다.
정리글: https://velog.io/@whow1101/13%EC%9E%A5-%EC%8A%A4%EC%BD%94%ED%94%84