TIL

<모던 자바스크립트 Deep Dive> 15장 let, const 키워드와 블록 레벨 스코프 요약 (1)

낭만인 2022. 2. 21. 21:58

15. let, const 키워드와 블록 레벨 스코프

1) var 키워드로 선언한 변수의 문제점

 

1. 변수 중복 선언 허용

- var 키워드로 선언한 변수는 같은 스코프 내에서 중복 선언이 가능

- 초기화문(변수 선언과 도시에 초기값을 할당하는 문) 유무에 따라 다르게 동작하는데, 초기화문이 있으면 자바스크립트 엔진이 var 키워드가 없는 것처럼 동작하며 초기화문이 없으면 자바스크립트 엔진이 변수 선언문을 무시함(에러 발생X)

- 변수 중복 선언 허용의 문제 : 의도와 달리 먼저 선언된 변수 값이 변경되는 부작용 발생

var x = 1;
var y = 1;

// 초기화문 있음 : var 키워드가 없는 것처럼 동작
var x = 100;
// 초기화문 없음 : 무시됨
var y;

console.log(x); // 100
console.log(y); // 1

 

 

2. 함수 레벨 스코프

- var 키워드로 선언한 변수는 함수의 코드 블록만 지역 스코프로 인정

- 함수 외부에서 var 키워드로 선언된 변수는 모두 전역 변수가 됨

- 함수 레벨 스코프의 문제 : 전역 변수가 남발될 가능성 -> 전역 변수가 중복 선언됨

var i = 10;

for (var i = 0; i < 5; i++) {
	console.log(i);
}

// 의도와 달리 변수 값이 변경됨
console.log(i); // 5

 

 

3. 변수 호이스팅

- var 키워드로 변수 선언 시 변수 호이스팅(변수 선언문이 스코프의 선두로 끌어올려짐) 발생

- 변수 선언문 이전에 변수를 참조할 수 있게 됨

- 변수 호이스팅의 문제 : 프로그램 흐름상 맞지 않으며 가독성을 떨어뜨리고 오류 발생시킴

// 변수 호이스팅에 의해 다른 어떤 코드보다 변수 foo가 먼저 선언됨
// 단, 값 할당은 코드 흐름의 순서에 따라 이루어지므로 그 전까지는 undefined 값을 가짐
console.log(foo); // undefined

foo = 123;

console.log(foo); // 123

// 변수 호이스팅으로, 제일 먼저 실행되는 문
var foo;

 

 

 

2) let 키워드

- ES6부터 var 키워드의 단점을 보완하기 위해 let, const 키워드가 도입됨

- var 키워드와 구분되는 let 키워드의 특징

 

1. 변수 중복 선언 금지

- let 키워드로 같은 이름의 변수를 중복으로 선언하면 문법 에러 발생

let bar = 123;
let bar = 456; // SyntaxError: Identifier 'bar' has already been declared

 

 

2. 블록 레벨 스코프

- let 키워드는 모든 코드 블록을 지역 스코프로 인정하는 블록 레벨 스코프를 따름

- 함수 내의 코드 블록은 함수 레벨 스코프와 중첩

let foo = 1; // 전역 변수

{
	let foo = 2; // 지역 변수
	let bar = 3; // 지역 변수
}

console.log(foo); // 1
console.log(bar); // ReferenceError: bar is not defined - 지역 변수이므로 참조 불가

 

 

3. 변수 호이스팅

- let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보여지나 변수 호이스팅이 이루어지고 있음

- var 키워드로 선언한 변수처럼 변수의 선언 단계는 런타임 이전에 실행되지만(변수 호이스팅), 초기화 단계는 변수 선언문에 도달해야 실행되므로 변수 선언문에 도달하여 실행하기 이전에 변수를 참조하면 에러가 발생하는 것

- 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없는 구간을 일시적 사각지대라 칭함

console.log(foo); // ReferenceError: foo is not defined

let foo; // 변수 선언문에서 초기화 단계가 실행됨
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행
console.log(foo); // 1

                                                                                                                                                                                               

- 변수 호이스팅이 발생하지 않는 것이 아니므로, 아래 예시처럼 스코프 체인의 규칙에 따라 현재 위치한 지역 스코프에서 먼저 변수를 참조하여 변수 호이스팅이 발생하고 있어 전역 변수 foo를 참조하는 것이 아니라, let 키워드의 특징에 따라 지역변수 foo를 참조하는데, 이는 선언은 하였지만 초기화는 이루어지지 않은 단계(일시적 사각지대에 빠짐)이므로 참조 에러를 발생시킴

let foo = 1; // 전역 변수

{
	console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
	let foo = 2; // 지역 변수
}

 

 

4. 전역 객체와 let

- var 키워드로 선언한 전역 변수, 전역 함수 그리고 선언하지 변수에 값을 할당한 암묵적 전역(전역 객체의 프로퍼티로 작용하나 변수는 아님)은 전역 객체 window의 프로퍼티가 됨

- 참조 시 window는 생략 가능

- 전역 객체 window의 프로퍼티는 전역 변수처럼 사용 가능

- let 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니므로 window로 접근 불가

var x = 1; // 전역 변수
y = 2; // 암묵적 전역
function foo() {} // 전역 함수

console.log(window.x); // 1
console.log(x); // 1
console.log(window.y); // 2
console.log(y); // 2
console.log(window.foo); // f foo() {}
console.log(foo); // f foo() {}


let z = 1;

console.log(window.z); // undefined
console.log(z); // 1

 

 

 

 

 

참고 : 도서 <모던 자바스크립트 Deep Dive>