[JavaScript] 자바스크립트 var, let, const 차이점, 호이스팅(Hoisting), for문 안에 setTimeout을 사용할 때 var와 let의 차이점
글 작성자: 망고좋아
반응형
🎯 호이스팅, Hoisting
📝 코드 실행 시 변수 처리
- JS 엔진이 코드를 읽으면 생성 단계에서 실행 컨텍스트 생성
- 함수 선언문은 실행 단계에서 함수 전체가 실행 컨텍스트에 저장
- var 변수는 저장 시 undefined로 초기화
- let, const는 초기화되지 않는다. 그냥 존재만 알고 있는 상태
- 초기화되지 않았기 때문에 접근하면 에러 발생
📝 코드로 알아보는 호이스팅
console.log(callMe()); // undefined
var x = 10;
console.log(callMe()); // 10
function callMe() {
return x;
}
- 호이스팅은 변수가 선언됨 시점보다 앞에서 사용되는 현상이다.
- 이는 var 변수가 생성 단계에서 undefined로 초기화되는 것이 원인이다.
- 함수는 생성 단계에서 함수 전체가 저장되므로 뒤에서 선언되어도 호출이 가능하다.
// error: Uncaught ReferenceError: Cannot access 'x' before initialization
console.log(callMe());
let x = 10;
console.log(callMe()); // 10
function callMe() {
return x;
}
- let, const 변수는 생성 단계에서 초기화되지 않는다.
- 선언문 이전에 접근 시 ReferenceErrorr가 발생한다.
- 이 경계를 Temporal Dead Zone(TDZ)라 한다.
- 따라서 let, const는 hoisting이 발생하지 않는다.
- x의 값이 초기화되지 않았기 때문에 접근하면 에러가 난다.
📝 var, let, const
- var, let, const 모두 변수를 선언하는 키워드이다.
- var, let은 변수에 재할당이 가능하지만, const는 재할당이 불가능하다.
- var는 함수 레벨 스코프, let과 const는 블록 레벨 스코프 변수이다.
function varFor() {
for (var i = 0; i < 3; ++i) {
setTimeout(() => {
console.log("i: ", i);
}, 0);
}
}
function letFor() {
for (let i = 0; i < 3; ++i) {
setTimeout(() => {
console.log("i: ", i);
}, 0);
}
}
varFor(); // 3 3 3
letFor(); // 0 1 2
- varFor에서 i는 varFor 함수 번위에 존재하는 변수이다.
- 따라서 setTimeout이 호출될 때 i는 for블록이 끝난 시점에 소멸하지 않는다.
- letFor에서 i는 for블록 안에 존재하는 변수이다.
- 각 for 블록이 실행되고 i는 소멸한다. 다만, 이 경우 각 화살표 함수의 closure에 저장된다.
📝 좀 더 알아보는 for문 안에 setTimeout을 사용할 때 var와 let의 차이점
- var는 함수 레벨 스코프
- let은 블록 레벨 스코프
- 블록은 if문, for문 while문 등으로 중괄호로 묶은 부분을 의미
function varFor() {
for (var i = 0; i < 3; ++i) {
console.log(i);
setTimeout(() => {
console.log("i: ", i);
}, 0);
}
}
varFor();
/*
출력 결과
0
1
2
i: 3
i: 3
i: 3
*/
var의 문제점
- for문 안에 setTimeout을 사용하면 클로저 문제가 발생된다.
- for문을 다 돌고 난 뒤 setTimeout이 실행된다. ⇒ 비동기 관련 문제
- for문은 속도가 빨라서 1초보다 훨씬 짧은 시간에 다음 i로 넘어가게 되어서 또다시 setTimeout을 실행한다. 이렇게 짧은 시간 안에 0~2까지 3번의 setTimeout이 실행된다.
- 즉, for문이 시작되고 나서 setTimeout의 콜백 함수는 모든 함수가 종료되고 난 뒤 실행된다. 따라서 setTimeout은 이미 값이 변경된 i를 볼 수밖에 없다. 따라서 3을 3번 반복해서 출력한다.
- 즉시 실행 컨텍스트로 문제를 해결할 수 있다. 또는 let을 사용
📌 참고
반응형
'프로그래밍 > JavaScript' 카테고리의 다른 글
[JavaScript] 자바스크립트 변수의 유효범위, 렉시컬 환경 (0) | 2021.11.16 |
---|---|
[JavaScript] 자바스크립트 블록레벨 스코프, 함수레벨 스코프 (0) | 2021.11.15 |
[JavaScript] 자바스크립트 전개 연산자란? (0) | 2021.11.13 |
[JavaScript] 자바스크립트 나머지 매개변수란? (0) | 2021.11.13 |
[JavaScript] 자바스크립트 클로저란? (0) | 2021.11.13 |
댓글
이 글 공유하기
다른 글
-
[JavaScript] 자바스크립트 변수의 유효범위, 렉시컬 환경
[JavaScript] 자바스크립트 변수의 유효범위, 렉시컬 환경
2021.11.16 -
[JavaScript] 자바스크립트 블록레벨 스코프, 함수레벨 스코프
[JavaScript] 자바스크립트 블록레벨 스코프, 함수레벨 스코프
2021.11.15 -
[JavaScript] 자바스크립트 전개 연산자란?
[JavaScript] 자바스크립트 전개 연산자란?
2021.11.13 -
[JavaScript] 자바스크립트 나머지 매개변수란?
[JavaScript] 자바스크립트 나머지 매개변수란?
2021.11.13