해결된 질문
작성
·
277
0
function testShadowing() {
let x = 5;
if (true) {
let x = 10;
console.log(x);
}
console.log(x);
}
testShadowing()
위와 같이 let으로 x 변수를 2번 할당했는데, 실제 메모리에는 어떻게 할당이 되나요?
블록 스코프라고 하더라도 함수 스코프 안에서 블록 스코프가 만들어 질 것으로 생각이 되는데(뇌피셜입니다.), 이미 함수 스코프에서 x라는 변수명을 사용하고 있어서 블록 스코프에서 x는 자바 스크립트 엔진에서 어떻게 받아들이고 실제 메모리에 어떤 식으로 메모리 할당을 하는지 궁금합니다.
답변 2
0
안녕하세요, 산성님! 질문 주셔서 감사합니다.
함수 스코프와 블록 스코프에서 같은 이름의 변수를 사용했을 때, 어떻게 메모리가 할당되는지를 질문하신 것 같아요.
예시 코드인 testShadowing 함수 안에서 let x = 5;로 변수 x를 선언했고 if 블록 안에서 let x = 10;으로 또 다시 변수 x를 선언했습니다.
이때 두 개의 x 변수는 각각 독립적으로 서로 다른 메모리 공간에 저장된답니다.
function testShadowing() {
let x = 5;
if (true) {
let x = 10;
console.log(x);
}
console.log(x);
}
testShadowing()
함수가 실행되면, 자바스크립트 엔진은 다음 순서로 동작합니다:
함수가 호출되면 실행 컨텍스트라는 특별한 공간이 만들어져요.
실행 컨텍스트 안에는 변수를 저장할 수 있는 환경이 마련되는데, 이걸 변수 환경이라고 합니다.
함수 안에 있는 변수들을 위한 공간이 변수 환경에 미리 만들어지는데요 var와 let, const 에 따라 초기값이 조금 다릅니다.
이때 let이나 const로 선언된 변수들은 uninitialized라는 상태가 됩니다.
반면에 var로 선언된 변수들은 undefined라는 값으로 초기화되죠
함수 코드가 한 줄씩 실행되면서 변수에 값이 할당되기 시작합니다.
let이나 const로 선언된 변수들은 선언문이 실행되기 전까지는 사용할 수 없어요. 그래서 이 기간을 일시적 사각지대(Temporal Dead Zone, TDZ)라고 합니다.
선언문이 실행되면 비로소 변수에 값이 할당되고, 변수를 사용할 수 있게 되는 것이죠.
testShadowing 코드에 위 단계를 대입해 보면:
testShadowing 함수가 호출되면 실행 컨텍스트가 만들어지고, 변수 x를 위한 공간이 만들어집니다.
let x = 5;가 실행되면서 변수 x에 값 5가 할당되죠
if 블록 안에서 let x = 10;이 실행되면, 새로운 블록 스코프가 만들어지고 그 안에 또 다른 변수 x가 생겨요. 이 x는 블록 바깥에 있는 x와는 다른 변수입니다.
블록 안에서 console.log(x);가 실행되면, 블록 안에 있는 x의 값인 10이 출력됩니다.
블록이 끝나면 블록 안에서 만들어진 x는 사라지게 됩니다. 즉 더 이상 접근할 수 없게 되는 것이죠.
함수 마지막에 있는 console.log(x);가 실행되면, 함수 바깥에 있는 x의 값인 5가 출력됩니다.
아래는 testShadowing 을 실행했을 때 스코프 체인의 모습니다. Block 스코프는 if 문 블럭 스코프를 Local 스코프는 testShadowing 함수 스코프를 나타냅니다. let 으로 x 변수를 선언 및 할당 했기 때문에 각 스코프마다 x 변수가 존재하는 것을 알 수 있습니다.
이렇게 let과 const 는 var 달리 블록 레벨 스코프를 갖기 때문에 서로 다른 스코프에서 같은 이름을 가진 변수를 여럿 선언하더라도 서로 다른 변수로 취급된다는 걸 알 수 있습니다. 이름이 같아서 하위 스코프의 변수가 상위 스코프의 변수를 가리는 이런 현상을 변수 쉐도잉이라고 합니다.
변수 쉐도잉이 발생하는 이유는 변수를 사용하려 할 때, 스코프 체인을 통해서 변수를 찾게 되는데 현재 실행 중인 코드에서 가장 가까운 스코프부터 찾기 때문입니다.
정리하면, 함수가 실행될 때 변수를 위한 공간은 미리 마련되지만, 실제로 변수에 값이 할당되는 건 해당 변수 선언문이 실행되는 시점이에요. 특히 let이나 const로 선언한 변수는 선언 전에 사용하려고 하면 에러가 발생하니 주의해야 합니다.
아래는 관련 수업의 링크입니다. 디버거를 같이 실행하면서 함수 실행 컨텍스트 및 스코프 체인을 설명하고 있어요. 참고하시면 좋을 것 같습니다.
- 함수 실행 컨텍스트 2편 - 다시 보는 함수 스코프와 블록 스코프
- 스코프 체인과 참조 오류
0
함수 스코프와 if 블록 스코프의 x 는 let 으로 선었기 때문에 블록 레벨 스코프를 갖습니다. 그래서 이름은 같을 지라도 전혀 다른(서로 다은 메모리 공간에 위치한) 변수입니다. 그래서 하나의 x를 5에서 10으로 값을 변경하는 일이 발생하지 않고 각 스코프에 있는 변수 x를 사용해 콘솔에 값을 출력합니다 😊