이 시리즈는 You Don't Know JS Yet (1판인 You Don't Know JS의 개정판) 을 가지고 스터디를 진행하면서 요약 정리한 글입니다. 내용에 대한 퀴즈도 깃헙 리포지토리에 올리고 있으니 참고하시면 더 도움이 되실 것 같습니다. 내용에 대해 오류가 있거나 궁금하신 점이 있다면 댓글 달아주세요!
지난 글에서 변수들의 작동 과정을 간략하게 알아봤는데, 컴파일러와 엔진이 변수를 찾아본다고 했지만 사실은 컴파일러 단계에서 변수의 위치는 거의 확정이 됩니다. 컴파일 과정에서 사용하는 변수의 위치를 찾고, 이 찾은 변수들은 변하지 않기 때문에 (불변 - immutable) 이 정보를 AST에 저장합니다. 그러기 떄문에 엔진은 컴파일러가 찾은 변수를 가져다 쓰기만 하는 것입니다.
다만 컴파일러가 이 변수의 위치를 최종적으로 확정하는 게 아닐 수 있습니다. 이전에 다룬 것 처럼 모듈을 사용하는 경우 현재 파일이 아닌 외부 파일에서 모듈을 들고 오는데, 이는 컴파일 과정에서 확인할 수는 없습니다. 따라서 최종적으로는 실행 단계에서 변수가 어디에서 가져오는지 알게 되지만, 주로 컴파일 단계에서 변수를 어디에서 가져오는지 대략적으로 확인할 수 있다라고 생각할 수 있습니다.
var studentName = "Suzy";
function printStudent(studentName) {
studentName = studentName.toUpperCase();
console.log(studentName);
}
printStudent("Frank"); // FRANK
printStudent(studentName); // SUZY
console.log(studentName); // Suzy
다른 언어들과는 다르게, 상위 스코프에 있는 변수 이름과 동일한 이름의 변수를 만들어도 변수를 사용할 수 있고, 이를 스코프 내부에서만 사용할 수 있습니다. 위 예시에서 studentName
은 printStudent()
함수 안 스코프에서는 밖 변수와는 다르게 작동하게 됩니다. 이를 JS에서 Shadowing이라고 합니다.
var studentName = "Suzy";
function printStudent(studentName) {
console.log(studentName);
console.log(window.studentName);
}
printStudent("Frank");
// "Frank"
// "Suzy"
만약 Shadowing을 없에고 싶다면 어떻게 써야 할까요? 브라우저 환경이라면 window
전역 변수를 사용한다면 최상단 스코프의 변수를 가져올 수 있습니다. 다만 이렇게 변수를 가져올려면 let
이나 const
로 변수를 선언하지 않고 var
로 선언해야 합니다.
function something() {
var special = "JavaScript";
{
let special = 42; // totally fine shadowing
}
}
function another() {
{
let special = "JavaScript";
{
var special = "JavaScript";
// ^^^ Syntax Error
}
}
}
또한 let
은 var
를 shadow 할 수 있지만, var
는 let
을 shadow 할 수 없습니다. 이는 var
의 호이스팅 때문에 변수 선언을 스코프 밖으로 나가게 되어, 상단에 있는 let
선언 변수와 충돌이 되기 때문입니다.
function another() {
{
let special = "JavaScript";
ajax("https://some.url", function callback(){
var special = "JavaScript"; // totally fine shadowing
});
}
}
다만 var
호이스팅은 함수 스코프 밖으로는 나가지 않기 때문에 위와 같이 함수 안에 있는 var
을 shadow하는 것은 아무 문제가 없습니다.
var askQuestion = function ofTheTeacher() {
"use strict";
ofTheTeacher = 42; // TypeError
};
askQuestion(); // TypeError
(작성중)