Javascript에서 Scope는 어떠한 참조 대상의 식별자를 찾아내기 위한 규칙이다.
여기서 말하는 식별자란 무엇일까?
식별자(identifier)는 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 이름이다.const a = "identifier" // String"identifier"라는 값을 가진 상수 a. 이때 a는 식별자라고 할 수 있다.
스코프는 크게 전역(Global) 스코프와 지역(Local / Function-Level) 스코프로 나눌 수 있다.
전역스코프는 코드 어디에서든 참조할 수 있다는걸 의미하고, 지역 스코프는 지역(함수), 블록이 만든 스코프로 해당 함수와 그 하위 함수에서만 참조할 수 있다.
ECMAScript6 이전에는 변수를 선언시 var라는 키워드만으로 변수를 선언하여 Javascript에서는 블록({}) 레벨로 스코프를 사용할 수 없었는데, let과 const라는 키워드가 도입된 후로 블록 레벨 스코프를 사용할 수 있게 되었다.
// var
var a = 1;
{
var a = 2;
console.log(a); // 2
}
console.log(a); // 2
// let
let b = 1;
{
let b = 3;
console.log(b); // 3
}
console.log(b); // 1
전역스코프와 지역스코프는 다음의 예시로 볼 수 있다.
let globalScope = "global"; // 전역스코프
function test() {
let localScope = "local"; // 지역스코프
console.log(globalScope);
console.log(localScope);
}
test();
// global
// local
console.log(globalScope);
// global
console.log(localScope);
// localScope is not defined
위 예시와 같이 전역에서 선언된 globalScope에는 함수내,외에서 호출이 가능한데, test라는 함수 안에서 선언된 localScope는 test함수 내에서만 호출이 가능하고 test함수 외에서는 호출이 불가하다.
그렇다면 만약 함수안에서 새로운 함수와 변수를 생성하여 값을 변형시킨다면 어떤 결과가 나올까?
let global = 10;
function test() {
let global = 100;
console.log(global); //100
function test2() {
global = 2000;
console.log(global); //2000 test()함수 내에서 선언된 global을 참조하여 값을 재할당
}
test2();
}
test();
console.log(global); //10 전역에서 선언된 global을 참조하여
위 예시와 같이 해당 스코프에 의해 global값을 참조하여 출력하는 결과를 볼 수 있다.
스코프는 함수를 어디서 호출하였는지에 따라 상위스코프를 결정하는 동적(dynamic)스코프 와 함수를 어디서 선언하였는지에 따라 스코프를 결정하는 렉시컬(Lexical or 정적 static)스코프로 나뉜다.
let value = 1;
function test() {
let value = 10;
function test2(){
console.log(value); //10 dynamic scope
}
test2();
test3();
}
function test3() {
console.log(value); //lexical scope
}
test(); // 1
test3(); // 1
위 예시와 같이 test함수내의 새로운 함수 test2에서는 value가 10으로 결정되었지만, test함수내에서 호출한 test3는 test함수 밖에있기때문에 함수를 어디서 선언하였는지를 따라가 value의 값이 1이 나온걸 볼 수 있다.
오늘 간단하게 스코프에 대해 알아보았는데, 스코프와 밀접한 관계가 있는 클로저, 호이스팅에 대해서도 이후 다뤄 볼 예정이다.