LHJ

I'm a FE developer.

7.5 변수 숨기기

05 May 2020 » js_lj

다른 스코프에 있으면서 이름이 같은 변수나 상수는 혼란을 초래할 때가 많습니다.
스코프 하나가 끝난 다음에 다른 스코프가 있는 식이라면 비교적 단순합니다.

{
	// 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) 이란 개념이 생겼습니다.
현재 스코프 체인에 있는 모든 변수는 스코프에 있는 것이며, 숨겨지지 않았다면 접근할 수 있습니다.