스코프는 변수(식별자)가 영향을 끼치는 범위를 말한다
let
const
로 선언된 변수는 블록 스코프를 가진다.var
로 선언된 변수는 함수 스코프를 가지기 때문에 블록 바깥까지 영향을 끼친다let x = 1;
{
let x = 2; // 블록 스코프를 가지기 때문에 해당 블록 내부에서만 영향을 준다
}
console.log(x) //1
let
은 블록 범위를 가지기 때문에 블록 범위 밖의 식별자에는 영향을 주지 않는다var x = 1;
{
var x =2; // 함수 스코프를 가지기 때문에 블록 외부에도 영향을 준다.
}
console.log(x);
var
변수는 블록문 외부의 식별자에 영향을 끼친다.스코프 체인이란 변수(식별자)를 찾기 위해 내부에서 외부까지 차례대로 검색해나가는 과정이다.
let a = 2;
let b = 3;
function foo(){
let b = 4;
console.log(a); // 2 스코프 체인에 의해 블록문 외부에서 식별자를 가져온다
console.log(b); // 4 가장 가까운 식별자를 찾으면 스코프 체인을 종료한다.
}
foo();
foo() 함수 내부에는 식별자 a
가 존재하지 않는다. 하지만 스코프 체인에 의해서 함수 외부에 존재하는 전역 스코프에 선언된 식별자 a
를 찾아 사용한다.
foo() 함수 내부와 외부에 모두 동일한 이름의 식별자 b
가 존재하는데, conosle.log()
가 호출된 가장 가까운 식별자를 찾기 때문에 foo() 함수 내부에 선언된 let b=4
식별자를 사용한다.
스코프 체인을 통해 가져온 외부 식별자를 기억하고 유지하고 있는 함수
function foo(){
let a = 1
return function(){
return ++a
}
}
const bar = foo();
bar() // 2
bar() // 3
a
를 증가시킨 후 return한다.a
가 존재하지 않기 때문에 스코프 체인
에 의해서 가장 가까운 범위의 식별자 let a=1
를 가져와 사용한다.foo
함수가 종료되었음에도 불구하고 bar
함수는 foo
함수에서 선언된 식별자 a
값을 사용하고 있다. 이 때, 식별자 a
에는 직접 접근할 수 없다.a
에 대한 참조가 살아있기 때문에 가바지컬렉터는 a
메모리를 지우지 않고 있는 상태이다. 이를 클로저
라고 한다.vs
let(const)var
는 함수 스코프를 가지고 let
const
는 블록 스코프를 가지기 때문에 변수의 유효범위가 다르다. 함수 스코프를 가진 var
를 사용하는경우 블록문 밖과 안에서 선언한 식별자를 중복하여 사용될 경우가 있기 때문에 사용을 지양해야한다.