var 키워드의 단점을 보완하기 위해 ES6에서는 새로운 변수 선언 키워드인 let과 const를 도입했다.
var 키워드와의 차이점을 중심으로 let 키워드를 살펴보자.
let
변수 중복 선언 금지
var
키워드로 이름이 동일한 변수를 중복 선언하면 아무런 에러가 발생하지 않는다.
이 경우 변수를 중복 선언하고 값을 할당하면 의도치 않게 먼저 선언된 변수 값이 재할당되어 변경되는 부작용이 발생한다.
아래 예제에서는 x
변수를 var
키워드로 두 번 선언하고 각각 다른 값을 할당했다.
var x = 10;
var x = 20;
console.log(x); // 20
첫 번째 선언에서 x
는 10가지지만, 두 번째 선언에서 20으로 재할당돼 기존 값이 덮여쓰여진다.
의도하지 않은 변수 값 변경을 유발할 수 있었다.
하지만 let
키워드에서는 동일한 이름의 변수를 중복 선언할 수 없도록 한다.
변수 중복 선언으로 인한 부작용을 방지할 수 있다.
let y = 10;
// let y = 20; // SyntaxError: Identifier 'y' has already been declared
y = 20;
console.log(y); // 20
블록 레벨 스코프
var
키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하는 함수 레벨 스코프를 따른다.
하지만 let
키워드로 선언한 변수는 모든 코드 블록을 지역 스코프로 인정하는 블록 레벨 스코프를 따른다.
블록 레벨 스코프와 let
let
키워드로 선언된 변수는 블록 레벨 스코프를 따른다.
따라서 코드 블록 내에서 선언된 변수는 해당 블록 내에서만 유효한 지역 변수가 된다.
let foo = 'global';
if (true) {
let foo = 'local';
console.log(foo); // local
}
console.log(foo); // global
위 예제에서 전역에서 선언된 foo
변수와 코드 블록 내에서 선언된 foo
변수는 서로 다른 별개의 변수다.
블록 내에서 선언된 foo
변수는 지역 변수로 취급되며, 블록을 벗어나면 전역의 foo
변수가 다시 참조된다.
또한 블록 내에서 선언된 변수는 블록이 종료되면 더 이상 참조할 수 없다. 블록 레벨 스코프가 변수의 유효 범위를 해당 블록으로 제한하기 때문이다.
if (true) {
let bar = 'block scoped';
console.log(bar); // block scoped
}
console.log(bar); // ReferenceError: bar is not defined
위 예제에서 bar 변수는 if 블록 내에서 선언되었기 때문에 블록 외부에서는 참조할 수 없다.
함수와 블록 레벨 스코프
함수도 코드 블록을 형성하므로 함수 내에서 let
으로 선언된 변수는 함수 스코프 내에서만 유효하다.
function example () {
let x = 10;
if (true) {
let x = 20;
console.log(x); // 20
}
console.log(x); // 10
}
example();
이 때 함수 example
내의 코드 블록은 함수 레벨 스코프 내에 중첩된다. if
블록 내에서 선언된 x
는 블록 내에서만 유효하며, 함수 레벨의 x
와는 별개의 변수이다.
변수 호이스팅
var
키워드로 선언한 변수와 달리 let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작한다.
let
키워드로 선언한 변수를 변수 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
변수 호이스팅 동작 방식
var
키워드로 선언한 변수는 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 “선언 단계”와 “초기화 단계”가 한 번에 진행된다.
선언 단계에서 스코프에 변수 식별자를 등록해 자바스크립트 엔진에 변수 존재를 알린다.
그리고 즉시 초기화 단계에서 undefined
로 변수를 초기화한다.
따라서 변수 선언문 이전에 변수에 접근해도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않으며 undefined
를 반환한다.
이후 변수 할당문에 도달하면 비로소 값이 할당된다.
console.log(x); // undefined
var x = 10;
console.log(x); // 10
위 예제에서 x
변수는 var
키워드로 선언되었기 때문에 호이스팅되어 선언 단계에서 undefined
로 초기화된다.
let
키워드와 호이스팅
let
키워드로 선언한 변수는 “선언 단계”와 “초기화 단계”가 분리되어 진행된다.
런타임 이전에 자바스크립트 엔진에 의해 선언 단계가 먼저 실행되지만, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.
만약 초기화 단계가 실행되기 이전에 변수에 접근하려고 하면 참조 에러가 발생한다.
console.log(y); // ReferenceError: y is not defined
let y = 20;
console.log(y); // 20
위 예제에서 y
변수는 let
키워드로 선언되었기 때문에, 초기화 단계 전에 변수를 참조하려고 하면 ReferenceError
가 발생한다.
일시적 사각지대(TDZ)
let 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없다.
스코프의 시작지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대$_{Temporal \space Dead \space Zone, \space TDZ}$라고 부른다.
{
console.log(z); // ReferenceError: z is not defined
let z = 30;
console.log(z); // 30
}
위 예제에서 z
변수는 블록 스코프 내에서 선언되었고 선언문 이전에 변수를 참조하려고 해 일시적 사각지대로 인해 ReferenceError
가 발생한다.
선언문 이후에는 정상적으로 변수를 참조할 수 있다.
let
키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보인다.
그러나 실제로는 호이스팅이 발생하지만 초기화 단계가 변수 선언문에 도달할 때까지 지연되기 때문에 일시적 사각지대가 발생한다.
이를 통해 변수 선언문 이전에 변수를 참조하려고 하면 참조 에러가 발생한다.
let foo = 'global';
if (true) {
console.log(foo); // ReferenceError: foo is not defined
let foo = 'local';
console.log(foo); // local
}
console.log(foo); // global
foo
변수는 let
키워드로 선언되었기 때문에 블록 내에서 호이스팅이 발생하지만, 초기화 단계가 지연돼 선언문 이전에 참조할 수 없다.
따라서 첫 번째 문에서 ReferenceError
가 발생하며 이후 foo
변수는 블록 내에서 정상적으로 참조된다.
references
'Web, Front-end' 카테고리의 다른 글
[Javascript] 이벤트 핸들러 등록 (0) | 2024.08.27 |
---|---|
[Javascript] const 키워드 (0) | 2024.06.05 |
[Javascript] var 키워드의 문제점과 호이스팅 (0) | 2024.06.05 |
[Javascript] 데이터 타입의 필요성 (0) | 2024.06.05 |
[React] 하나의 index.ts에서 import 및 export 하기 (0) | 2024.05.09 |
컴퓨터 전공 관련, 프론트엔드 개발 지식들을 공유합니다. React, Javascript를 다룰 줄 알며 요즘에는 Typescript에도 관심이 생겨 공부하고 있습니다. 서로 소통하면서 프로젝트 하는 것을 즐기며 많은 대외활동으로 개발 능력과 소프트 스킬을 다듬어나가고 있습니다.
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!