다른 스코프에 있으면서 이름이 같은 변수나 상수는 혼란을 초래할 때가 많습니다.
스코프 하나가 끝난 다음에 다른 스코프가 있는 식이라면 비교적 단순합니다.
{
// block 1
const x = 'blue';
console.log(x); // "blue"
}
console.log(typeof x); // "undefined"; x는 스코프 밖에 있습니다.
{
// block 2
const x = 3;
console.log(x); // "3"
}
console.log(typeof x); // "undefined"; x는 스코프 밖에 있습니다.
앞 예제의 x는 다른 스코프에 있는, 이름만 같은 두 개의 변수임을 이해하기 쉽습니다.
이제 스코프가 중첩되는 경우를 살펴봅시다.
{
// 외부 블록
let x = 'blue';
console.log(x); // "blue"
{
// 내부 블록
let x = 3;
console.log(x); // "3"
}
console.log(x); // "blue"
}
console.log(typeof x); // "undefined"; x는 스코프에 있지 않습니다.
이 예제는 변수 숨김(variable masking) 을 잘 보여줍니다.
내부 블록의 x는 외부 블록에서 정의한 x와는 이름만 같을 뿐 다른 변수이므로 외부 스코프의 x를 숨기는(가리는) 효과가 있습니다.
여기서 이해해야 할 중요한 점은, 실행 흐름이 내부 블록에 들어가 새 변수 x를 정의하는 순간, 두 변수가 모두 스코프 안에 있다는 겁니다.
변수의 이름이 같으므로 외부 스코프에 있는 변수에 접근할 방법이 없습니다.
x 하나가 스코프에 들어갔다가 나오고, 다른 x가 같은 행동을 반복한 이전 예제와 비교해 보십시오.
다음 예제를 보면 더 자세히 알 수 있습니다.
{
// 외부 블록
let x = { color: "blue" };
let y = x; // y와 x는 같은 객체를 가리킵니다.
let z = 3;
{
// 내부 블록
let x = 5; // 이제 바깥의 x는 가려졌습니다.
console.log(x); // 5
console.log(y.color); // "blue"; y가 가리키는 외부 스코프의 x가 가리키는 객체는 스코프 안에 있습니다.
y.color = "red";
console.log(z); // 3; z는 숨겨지지 않았습니다.
}
console.log(x.color); // "red"; 객체는 내부 스코프에서 수정됐습니다.
console.log(y.color); // "red"; x와 y는 같은 객체를 가리킵니다.
console.log(z); // 3
}
NOTE_
외부 스코프에 있는 같은 이름의 변수에 그늘이 진 듯 만든다는 의미에서 변수 숨김을 변수 섀도우(shadowing) 라 부르기도 합니다.
하지만 그늘이 진다 해도 완벽히 가려지는 것이 아니라 어두워질 뿐이므로 필자는 이 용어를 사용하지 않습니다.
변수를 숨기면 그 변수는 해당 이름으로는 절대 접근할 수 없습니다.
이제 스코프가 계층적임을 이해했을 겁니다.
이전 스코프를 떠나지 않아도 새 스코프에 진입할 수 있습니다.
스코프의 계층적인 성격 때문에 어떤 변수가 스코프에 있는지 확인하는 스코프 체인(scope chain) 이란 개념이 생겼습니다.
현재 스코프 체인에 있는 모든 변수는 스코프에 있는 것이며, 숨겨지지 않았다면 접근할 수 있습니다.