이번 주 강의를 들으면서 let const 차이를 배우면서, 예전에 기술면접을 공부할 때 호이스팅을 생각하면서 정리를 하였습니다.
자바스크립트가 ES6 이전 버전에는 var을 사용하였습니다.
var tester = "hey hi";
function newFunction() {
var hello = "hello";
}
console.log(hello); // error: hello is not defined
var greeter = "hey hi";
var greeter = "say Hello instead";
console.log(greeter); // say Hello instead
var greeter = "hey hi";
greeter = "say Hello instead2";
console.log(greeter); // say Hello instead2
위 와 같이 코드를 짜도 에러가 발생하지 않습니다.
var greeter = "hey hi";
var times = 4;
if (times > 3) {
var greeter = "say Hello instead";
}
console.log(greeter) // "say Hello instead"
time > 3가 true를 반환하기 때문에 greeter는 "say Hello instead"로 재정의됩니다. 의도적으로 재정의한 것이라면 괜찮겠지만, 변수 greeter가 이미 정의되어 있다는 사실을 인식하지 못한 경우에는 문제가 됩니다.
또한, 다른 코드의 부분에서 greeter가 사용되어진다면 원하는 출력 결과를 얻을 수 없는 경우가 생기게됩니다.
ES6에서 var선언에 대한 개선을 반영한 변수 선언
let greeting = "say Hi";
let times = 4;
if (times > 3) {
let hello = "say Hello instead";
console.log(hello); // "say Hello instead"
console.log(greeting); // say hi
}
console.log(hello); // hello is not defined
let greeting = "say Hi";
greeting = "say Hello instead";
console.log(greeting); // say Hello instead
let greeting = "say Hi";
let greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared
만약 let변수가 다른 블록 즉, let으로 선언된 동일한 변수가 다른 범위 내에서 정의된다면 에러가 발생하지 않습니다.
let greeting = "say Hi";
if (true) {
let greeting = "say Hello instead";
console.log(greeting); // "say Hello instead"
}
console.log(greeting); // "say Hi"
요즘 코드는 거의 const입니다. const는 일정한 상수 값을 유지합니다.
const greeting = "say Hi";
greeting = "say Hello instead";// error: Assignment to constant variable.
const greeting = "say Hi";
const greeting = "say Hello instead";// error: Identifier 'greeting' has already been declared
따라서 const는 선언과 동시에 초기화가되어야 합니다.
const arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]
const obj = { a: 1, b: 2 };
obj.c = 3;
obj.a = 4;
console.log(obj); // { a: 4, b: 2, c: 3 }
호이스팅이란?
자바스크립트 코드가 실행될 때 실행 컨텍스트 환경에서 "생성 단계"에서 발생합니다.
호이스팅은 코드가 실행하기 전 변수선언/함수선언이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상 즉, 변수 및 함수 선언을 먼저 하는 과정입니다.
3-2-1. 생성 단계
- 실행 컨텍스트 생성
- 선언문만 실행해서 Environment Record에 기록 (실행 컨텍스트에 저장) -> 호이스팅
3-2-2. 실행 단계
- 선언문 외 나머지 코드 순차적 실행
- 실행 컨텍스트에 저장된 정보 참조 또는 업데이트
이러한 단계들을 거쳐서 실행 컨텍스트를 구성한다.
이렇게 알게된 호이스팅으로 var let const의 호이스팅에 대해 알아보았습니다.
console.log(greeter); // undefined
var greeter = "say hello"
위 코드가 실행되면 undefined가 뜹니다
실행컨텍스트의 레코드에서는 아래와 같은 단계가 이루어집니다
// 생성단계
var greeter; // 1. 선언
greeter = undefined // 2.초기화
console.log(greeter) // undefined
// 실행단계
greeter = "say hello" // 3. 할당
var은 호이스팅에서 생성단계에서 선언과 초기화가 동시에 이루어집니다.
console.log(greeter); // greeter가 선언은 되었지만 초기화 x -> TDZ
let greeter = "say hello"; // 초기화 -> 할당
// ReferenceError: Cannot access 'greeter' before initialization
console.log(greeter); // TDZ
const greeter = "say hello"; // 선언 -> 초기화 -> 할당
// ReferenceError: Cannot access 'greeter' before initialization
const let은 var과 다르게 변수에 값이 할당되기 전에 접근 할 경우 참조에러가 발생합니다.
이를 TDZ(Temporal Dead Zone)일시적 사각지대 라고 합니다 -> 선언 이전에 식별자를 참조할 수 없는 구역
TDZ로 우리는 코드의 실수를 줄일수 있다는 이점이 있다고합니다.
let, const 키워드로 변수를 선언한 경우, 값을 undefined로 선언하지 않기 때문에 할당 문 직전까지 변수에 아무런 값이 담겨 있지 않아, 접근하고자 하면 error가 발생합니다. 선언 라인 이전에 변수를 참조할 수 없다는 것을 의미합니다.
참고사이트
[JS] 실행 컨텍스트(Execution Context)
Var, Let, Const의 차이점은?
[JavaScript] 호이스팅(Hoisting)