개발자
TDZ: 선언위치부터 초기화되는 구간에서 호출 시 참조에러발생 (초기화 전 호출시 에러) 아래 예시에서 호이스팅에 의해 let a 가 먼저 실행되는건똑같은데 왜 1번은 언디파인드이고 2번은 참조에러인지 이해가안가네요. 특히 2번에서도 let a 는 호이스팅돼서 1번과 동일한 형태가 된다고 생각하는데, 확실하게 이해가안갑니다. 1. let a; console.log(a); a = 3; 2. console.log(a); let a = 3;
답변 3
인기 답변
호이스팅의 개념은 자바스크립트가 코드를 평가하고 실행하는 것과 변수를 선언하고 초기화하는 시점에 의해 발생하는 현상입니다. 자바스크립트 엔진은 소스 코드를 실행하는 단계(런타임)에 앞서, "코드를 평가하는 단계"가 존재하고, 이 평가 단계에서는 2가지 일을 수행합니다. 1. 소스 코드에 해당하는 실행 컨텍스트를 생성 2. 소스 코드의 변수, 함수 등의 선언문만 먼저 실행하여 실행 컨텍스트가 관리하는 스코프에 변수/함수 등의 식별자를 등록 질문자분께서 말씀해주신 "선언"이라는 것은 이 평가단계에서 이루어지는 과정, 즉 스코프에 변수의 식별자를 등록하는 과정입니다. 그렇다면 초기화는 무엇일까요? 초기화는 변수의 값을 저장하기 위해, 메모리를 할당해주고 그 초기값을로 undefined를 배정해주는 과정입니다. 초기화는 변수를 어떻게 선언해주었느냐에 따라 다릅니다. var로 선언한 변수의 경우에는 선언과 함께 초기화가 이루어집니다. 하지만 let, const로 선언된 변수의 경우 코드를 실행하는 중 변수 선언문을 만난 시점에서 실행되게 됩니다. 위의 지식을 우리는 알게 되었으니 질문자분께서 주신 예시를 통해 한번 같이 살펴보겠습니다. 1. // 코드가 실행되는 이 시점에서 평과과정을 마무리하여 스코프는 모든 변수들을 알고 있습니다. // 변수 a는 스코프에 등록이 되어있지만(선언) 아직 메모리를 할당받지 못했습니다.(초기화가 되지 않음) let a; // => 이 지점에서 a의 변수가 초기화 되어 undefined의 값을 받았습니다. console.log(a); // => 그렇기 때문에 여기서 undefined의 값을 확인할 수 있습니다. a = 3; 2. // 1번과 마찬가지로 코드가 실행되는 시점에서 스코프는 모든 변수의 식별자를 동록했습니다. // 변수 a는 let으로 선언되었기 때문에 아직 초기화 되지 않았습니다. console.log(a); // => 아직 메모리가 할당되지 않은 변수를 참조하려 합니다. // 아직 메모리가 없는 값, 즉 참조가 불가능한 변수를 읽으려 하기 때문에 자바스크립트 엔진은 참조에러를 띄우게 됩니다. let a = 3; // => a의 변수는 이 시점에서 초기화와 할당이 같이 이루어 지게 됩니다. 이렇게, let/const는 코드를 시작하기 전 값이 선언이 되어 있지만, 실행 중 선언문을 만나기 전까지는 값을 초기화 하지 못하고 이로 인해 참조할 수 없는 구간이 생기게 됩니다. 이를 일시적 사각 지대(Temporal Dead Zone)이라고 합니다. 만일 변수 a를 var로 선언한다면, 질문자분께서 예측하신 것처럼 동작하게 될것입니다.
익명
작성자
2024년 04월 24일
답변주셔서 감사합니다. var , let const 차이는 알것같은데 2번예시에서 let a = 3 했을때 let a 가 호이스팅돼서 최상위로 올라가는것이면 1 번예시랑 뭐가다른건지 모르겠습니다..1번예시도 let a가 최상위로 올라간건데 2번예시에서 코드작성 시 애초부터 a의값은 3이라고 할당을 해주어서 그런걸까요..?
김용현
네이버 파이낸셜 • 2024년 04월 24일
제 잘못된 추측일 수 있지만, 아마 질문자분께서는 호이스팅이란 실제 물리적으로 코드가 최상단에 올라가는 것이라고 생각하시는 것 같습니다.("let a 가 호이스팅돼서 최상위로 올라가는것"이라고 말씀하시는 것으로 추측해봅니다.) 하지만 실제로 코드는 최상위로 올라가지 않습니다. 호이스팅은 "마치 선언하는 게 올라가는 것처럼 동작하는 것"이지, 실제로 선언부 코드가 올라가는 것이 아닙니다. 위에 제가 작성한 설명 혹은 아래의 소지우님께서 작성해주신 것과 같이, 자바스크립트는 코드를 실행하기에 앞서 "평가 과정"을 거쳐 실행 컨텍스트에 변수의 식별자를 기록합니다. 그래서 코드의 런타임에서 실행하는 부분이 아직 변수의 선언문이 아니더라도 해당 변수를 알고 있는 것처럼 동작하는 현상이 발생하는 것입니다. 이것이 호이스팅입니다. 그래서 코드의 "선언"(var의 경우에는 초기화도 함께 하지만, let/const는 오직 선언만!)하는 부분이 위로 올라온 것처럼 보이는 것입니다. 정리해서 말하자면 let a라고 선언하는 문장이 최상단으로 올라가는 것이 아니라, 자바스크립트 엔진은 "코드를 평가"하는 것을 통해 변수의 선언부 코드를 읽기 전에 그 변수의 "식별자"를 알고 있는 것을 말합니다. (절대로 우리가 작성한 코드의 순서를 자바스크립트 엔진이 임의로 옮기지 않습니다, 만일 그렇다면 자바스크립트에 우리가 위치에 맞추어 코드를 선언하는 의미가 있을까요?) 그리고 let의 선언하는 것만 미리 처리되었고, 실제 코드의 실행부분이 `let a` 만나기 전까지 초기화 되지 않는 것입니다. 1번 예시는 let a가 위에 있기 때문에 해당 a 식별자에 메모리가 할당되고 undefined라는 값을 넣게 된 것이고, 2번 예시는 console.log가 초기화 되기전에 실행 되었기 때문에 참조 에러가 발생한 것입니다. 개인적으로 질문자분께서 호이스팅을 제대로 이해하고 싶은 생각이시라면, 조금 어렵더라도 렉시컬 환경과 환경 레코드에 어떻게 변수들이 저장되는지를 학습하시는 것이 큰 도움이 될 것 같습니다.
인기 답변
호이스팅은 자바스크립트 엔진이 코드를 전역적으로 평가하고, 변수들을 먼저 메모리에 등록하는 동작에서 발생하는 현상입니다. 아직 실행되기 전에 미리 필요한 변수들을 메모리에 저장을 하기 때문에 선언문이 마치 최상단으로 끌어올려진 듯한 현상이 발생합니다. 평가 단계에서의 각 var, let, const 키워드는 공통적으로 식별자를 메모리에 먼저 기억을 해두고, 식별 값 초기화는 var 키워드만 진행합니다. var는 식별자를 등록하고 undefined으로 초기화하지만, let, const는 식별자를 등록한 후, 초기화를 하지 않아 식별할 수 없는 상태입니다. var는 undefined으로 초기화되기에 식별값을 가져올 수 있고, 선언문 이전에도 undefined이 출력됩니다. 반대로 let, const는 식별자를 등록하지만 선언문 이전에 호출하고자 한다면 선언문 이전에는 식별값이 등록되지 않기 때문에 refference error ( TDZ ) 일시적 사각 지대 가 발생합니다. -- 이어서 작성해 주신 코드를 시각적으로 보여드리겠습니다. 1번 -------------- 평가 a 확인 -> a 식별자 등록 -------------- 실행 let a; // undefined 식별값 등록 console.log(a); // undefined 출력 a = 3; // 3 식별값 등록 -------------- 2번 -------------- 평가 a 확인 -> a 식별자 등록 -------------- 실행 console.log(a); // a 식별자 확인 -> a 식별값 확인 불가 -> refference error let a = 3; // 3 식별값 등록 console.log(a); // 3 출력 -------------- var의 경우 -------------- 평가 a 확인 -> a 식별자 등록 -> undefined으로 초기화 -------------- 실행 console.log(a); // undefined var a = 3; // 3 식별값 등록 console.log(a); // 3 출력 -------------- 이상 도움이 되었다면 좋겠습니다.
익명
작성자
2024년 04월 25일
감사합니다! 그럼 let, const 경우 코드의 흐름상 실제로 선언문에 도달했을 때 초기화가 이루어진다. 그전까지는 TDZ에 속하기에 에러가 발생한다. 가 맞을까요~?!
소지우
프론트엔드 개발자 • 2024년 04월 25일
네, 선언문에 도달했을 때 식별자를 보고 메모리에 등록된 동일한 식별자에 입력한 식별값을 연결시켜주기에 그런 현상이 발생합니다. 말씀처럼 선언문에 도달하게 되어 식별값이 있다면 식별값 연결, 반대로 let a;라고 되어있다면 자동으로 초기화 메커니즘에 기인하여 undefined이 할당됩니다. 그 전까지는 식별할 수가 없기에 참조할 수가 없어 TDZ 일시적 사각 지대가 발생하는 것이죠.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 04월 24일
호이스팅(hoisting)은 변수, 함수 선언을 실제 코드의 상단으로 끌어올리는 JavaScript의 작동 방식입니다. 그러나 let과 const를 사용하는 변수들에게 hoisting이 적용될때 일부 차이점이 있습니다. 이 차이점이 바로 Temporal Dead Zone(TDZ)라고 불리는 개념입니다. TDZ는 변수가 메모리에 할당되었지만 아직 값을 가지지 않은 상태를 말합니다. 1번 예제: ```javascript let a; console.log(a); //undefined a = 3; ``` 위의 경우, let변수 a가 호이스팅 되긴하지만, TDZ(Temporal Dead Zone) 내에 있어서 'undefined'값을 갖습니다. 이후 선언된 a = 3; 이 실행되면 값을 대입받아 'undefined'에서 3으로 값이 변경됩니다. 2번 예제 : ```javascript console.log(a); //ReferenceError: Cannot access 'a' before initialization let a = 3; ``` 위의 경우도, let변수 a가 호이스팅 되긴하나, 호출된 시점에서는 아직 TDZ 내에 있으므로 초기화 전인 상태입니다. 그래서 참조 에러(ReferenceError)가 발생하는 것입니다. 여기서 코드 실행은 중단됩니다. 따라서, let과 const 키워드로 선언된 변수들은 호이스팅되긴 하지만, 실제 값이 할당되기 전까지는 그 변수들을 참조할 수 없도록 TDZ라는 메커니즘이 적용됩니다. 이런 특성 때문에 let과 const를 사용하면 var를 사용할 때보다 예상치 못한 버그를 방지하고 더욱 안전한 코드를 작성할 수 있습니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!