[모던 자바스크립트 Deep Dive]15장 let, const 키워드와 블록 레벨 스코프
15.1 var
키워드로 선언한 변수의 문제점
15.1.1 변수 중복 선언 허용
- 초기화 문: 변수 선언과 동시에 초깃값을 할당하는 문
1
2
3
4
5
6
7
8
9
10
11
var x = 1;
var y = 1;
// var 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용한다.
// 초기화문이 있는 변수 선언문은 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작
var x = 100;
// 초기화문이 없는 변수 선언문은 무시된다.
var y;
console.log(x); // 100
console.log(y); // 1
- 초기화 문이 있는 변수 선언문: 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작
- 초기화 문이 없는 변수 선언문: 무시
15.1.2 함수 레벨 스코프
- 오직 함수의 코드 블록만을 지역 스코프로 인정
15.1.3 변수 호이스팅
- 변수 선언문 이전에 변수 참조 가능
- 가독성 떨어뜨리고 오류 발생 가능성 높음
15.2 let
키워드
var
키워드의 단점을 보완하기 위해 ES6에서 도입
15.2.1 변수 중복 선언 금지
- 변수를 중복으로 선언하면
SyntaxError
발생
15.2.2 블록 레벨 스코프
1
2
3
4
5
6
7
8
9
let foo = 1; // 전역 변수
{
let foo = 2; // 지역 변수
let bar = 3; // 지역 변수
}
console.log(foo); // 1
console.log(bar); // ReferenceError: bar is not defined
- 모든 코드 블록(함수,
if
문,for
문,while
문,try
/catch
문 등)을 지역 스코프로 인정
15.2.3 변수 호이스팅
let
키워드로 선언한 변수를 변수 선언문 이전에 참조하면ReferenceError
발생1 2 3 4 5 6 7 8 9
// 런타임 이전에 선언 단계가 실행된다. 아직 변수가 초기화되지 않았다. // 초기화 이전의 일시적 사각지대에서는 변수를 참조할 수 없다. console.log(foo); // ReferenceError: foo is not defined let foo; // 변수 선언문에서 초기화 단계가 실행된다. console.log(foo); // undefined foo = 1; // 할당문에서 할당 단계가 실행된다. console.log(foo); // 1
- 초기화 단계 이전에 변수에 접근하기 때문
일시적 사각지대(TDZ, Temporal Dead Zone): 변수를 참조할 수 없는 구간, 즉 스코프의 시작 시점 ~ 초기화 시작 지점
코드 단계 실행 결과 선언 단계 ReferenceError
일시적 사각지대 ReferenceError
let foo;
초기화 단계 foo === undefined
foo = 1;
할당 단계 foo === 1
let
키워드로 선언한 변수는 런타임 이전에 선언단계 실행 뒤, 변수선언문에 도달하면 초기화 단계 실행- 선언 단계: 스코프에 변수 식별자 등록
- 스코프: 실행 컨텍스트의 렉시컬 환경
- 초기화 단계:
undefined
로 변수 초기화 var
키워드로 선언한 변수는 런타임 이전에 선언단계, 초기화 단계 둘 다 실행
- 선언 단계: 스코프에 변수 식별자 등록
- 사실 자바스크립트는 모든 선언을 호이스팅한다.
var
,let
,const
,function
,function*
,class
등 모든 선언 포함let
,const
,class
는 호이스팅이 발생하지 않는 것처럼 동작할 뿐
1 2 3 4 5 6 7
let foo = 1; // 전역 변수 { console.log(foo); // ReferenceError: Cannot access 'foo' before initialization let foo = 2; // 이 지역 변수는 호이스팅되어 TDZ에 빠지기 때문에 // 전역 변수 foo가 출력되지 못하고 ReferenceError가 발생한다. }
15.2.4 전역 객체와 let
var
키워드로 선언한 전역 변수, 전역함수, 암묵적전역 ⇒ 전역객체window
의 프로퍼티1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// 전역 변수 var x = 1; // 암묵적 전역 y = 2; // 전역 함수 function foo() {} // var 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티다. console.log(window.x); // 1 // 전역 객체 window의 프로퍼티는 전역 변수처럼 사용할 수 있다. console.log(x); // 1 // 암묵적 전역은 전역 객체 window의 프로퍼티다. console.log(window.y); // 2 console.log(y); // 2 // 함수 선언문으로 정의한 전역 함수는 전역 객체 window의 프로퍼티다. console.log(window.foo); // ƒ foo() {} // 전역 객체 window의 프로퍼티는 전역 변수처럼 사용할 수 있다. console.log(foo); // ƒ foo() {}
- 전역 객체의 프로퍼티 참조시
window
생략 가능 - 암묵적 전역: 선언하지 않은 변수에 값을 할당
- 전역 객체의 프로퍼티 참조시
let
키워드로 선언한 전역 변수 ⇒ 전역 객체의 프로퍼티 아님1 2 3 4 5
let x = 1; // let, const 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티가 아니다. console.log(window.x); // undefined console.log(x); // 1
- 이들은 전역 렉시컬 환경의 선언적 환경 레코드 내에 존재
15.3 const
키워드
15.3.1 선언과 초기화
- 반드시 선언과 동시에 초기화 해야한다.
1
const foo; // SyntaxError: Missing initializer in const declaration
- 블록 레벨 스코프를 갖는다.
- 호이스팅이 발생하지 않는 것 처럼 동작한다.
1 2 3 4 5 6
{ // 변수 호이스팅이 발생하지 않는 것처럼 동작한다 console.log(foo); // ReferenceError: Cannot access 'foo' before initialization const foo = 1; console.log(foo); // 1 }
15.3.2 재할당 금지
1
2
const foo = 1;
foo = 2; // TypeError: Assignment to constant variable.
- 재할당할 수없다.
15.3.3 상수
const
키워드로 선언된 변수에 원시 값을 할당하면 할당된 값은 변경 불가능- 원시 값: 변경불가능한 값(immutable value)
- 상수를 사용하면 유지보수성 상승
상수는 일반적으로 대문자로 이루어진 스네이크 케이스로 표현
1 2 3 4 5 6 7 8 9 10 11
// 세율을 의미하는 0.1은 변경할 수 없는 상수로서 사용될 값이다. // 변수 이름을 대문자로 선언해 상수임을 명확히 나타낸다. const TAX_RATE = 0.1; // 세전 가격 let preTaxPrice = 100; // 세후 가격 let afterTaxPrice = preTaxPrice + preTaxPrice * TAX_RATE; console.log(afterTaxPrice); // 110
15.3.4 const
키워드와 객체
1
2
3
4
5
6
7
8
const person = {
name: "Lee",
};
// 객체는 변경 가능한 값이다. 따라서 재할당없이 변경이 가능하다.
person.name = "Kim";
console.log(person); // {name: "Kim"}
const
키워드로 선언된 변수에 객체를 할당하면 값을 변경 가능
15.4 var
vs. let
vs. const
- ES6를 사용한다면
var
는 사용하지 않는다. - 재할당이 꼭 필요하다면 스코프를 최대한 좁게 만들고
let
을 사용한다. - 기본적으로
const를
사용한다.
This post is licensed under CC BY 4.0 by the author.