모던 자바 스크립트 Deep Dive 를 읽고 정리한 글 입니다.
15. 1 var 키워드로 선언한 변수의 문제점(특징)
변수 중복 선언 허용
var 키워드로 선언한 변수를 중복 선언하면 초기화문(변수 선언과 동시에 초기값을 할당하는 문) 유무에 따라 동작
동일한 이름의 변수를 중복 선언하며 값을 할당한다면 기존 변수 값이 변경
- 초기화문이 있는 변수 선언문 : var 키워드가 없는 것처럼 동작
- 초기화문이 없는 변수 선언문 : 무시(에러발생하지 않음)
// var 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언 허용
var x = 1;
var y = 1;
var x = 100; // 초기화문이 있는 변수 선언문 : var 키워드가 없는 것처럼 동작
var y; // 초기화문이 없는 변선 선언문 : 무시
console.log(x); // => 100
console.log(y); // => 1
함수 레벨 스코프
함수의 코드블록만을 지역 스코프로 인정
함수 외부에서 var 키워드로 선언한 변순느 코드 블록 내에서 선언해도 전역 변수화
var x = 1;
if(true) {
var x = 10; // 전역변수 x의 중복 선언으로 변수값 변경
}
console.log(x); // => 10
for문의 변수 선언문에서 var 키워드로 선언한 변수도 전역 변수 화
var i = 10;
// for문에서 전역변수 i의 중복 선언으로 변수값 변경
for (var i = 0; i < 5;, i++) {
console.log(i); // 0 1 2 3 4
}
console.log(i) // => 5
변수 호이스팅
변수 선언문이 스코프의 선두로 끌어 올려진 것처럼 동작
변수 호이스팅에 의해 var 키워드로 선언한 변수는 변수 선언문 이전에 참조 가능
할당문 이전에 변수 참조시 undefined 반환
에러는 발생하지 않지만 가독성 저하
선언 단계, 초기화 단계 동시진행
// 1. 선언 단계 - 변수 호이스팅에 의해 foo 변수 선언
// 2. 초기화 단계 - 변수 foo는 undefined로 초기화
console.log(foo); // =>undefined
// 3. 할당 단계 : 변수에 값을 할당
foo = 123;
console.log(foo); // => 123
//변수 선언은 런타임 이전에 암묵적 실행
var foo;
15. 2 let 키워드
변수 중복 선언 금지
var 키워드와 달리 동일 이름 변수 중복 선언시 문법 에러 발생
블록 레벨 스코프
모든 코드 블록을 지역 스코프로 인정
let foo = 1; // 전역 변수
{
let foo = 2; // 지역 변수
let bar = 3; // 지역 변수
}
console.log(foo); // => 1
console.log(bar); // => ReferenceError:bar is not defined
변수 호이스팅
변수 호이스팅이 발생하지 않는 것처럼 동작
변수 선언문(초기화 단계) 이전에 참조하면 참조에러 발생
선언 단계, 초기화 단계 분리되어 진행
일시적 사각지대 : 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간
// var 키워드로 선언한 변수는 런ㅏ임 이전에 선언 단계 초기화 단계 실행
// 변수 선언문 이전에 변수 참조 가능
console.log(foo); // => undefined
var foo;
console.log(foo); // => unedfined
foo = 1; // 할당문에서 할당 단계 실행
console.log(foo); // => 1
--------------------------------------------------------------------
// 런타임 이전에 선언 단계 실행, 변수 초기화 아직 안됌
// 초기화 이전의 일시적 사각지대에서는 변수 참조 불가
console.log(foo); // => ReferenceError: foo is not defined (호이스팅 발생)
let foo; // 변수 선언문에서 초기화 단계 실행
console.log(foo); // => unedfined
foo = 1; // 할당문에서 할당 단계 실행
console.log(foo); // => 1
전역 객체와 let
전역 객체의 프로퍼티가 아님
let 변수는 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드)내에 존재
// 전역 변수
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
// 함수 선언문으로 정의한 전역 함수는 전역 객체 windw의 프로퍼티
console.log(window.foo); // => f foo() {}
// 전역 객체 window의 프로퍼티는 전역 변수처럼 사용 가능
console.log(foo); // => f foo() {}
------------------------------------------------------------------------
let x = 1;
// let, const 키워드로 선언한 전역 변수는 전역 변수 window의 프로퍼티가 아님
console.log(window.x); // => undefined
console.log(x); // => 1
15. 3 const 키워드
대부분 let 키워드와 동일
선언과 초기화
선언과 동시에 초기화하지 않으면 에러 발생
블록레벨 스코프
호이스팅이 발생하지 않는 것처럼 동작
const foo = 1;
const foo; // SyntaxError: Missing initializer in const declaration
-------------------------------------------------------------------------
{
// 변수 호이스팅이 발생하지 않는 것처럼 동작
console.log(foo); // ReferenceError: Cannot axxess 'foo' before initialization
const foo = 1;
console.log(foo); // => 1
}
// 블록 레벨 스코프를 가짐
console.log(foo); // ReferenceError: foo is not defined
재할당 금지
var, let 키워드 변수는 자유로운 재할당 가능
const 키워드 변수는 재할당 금지
상수
- 변수 : 재할당 가능 변수
- 상수 : 재할당이 금지된 변수
const 키워드로 선언된 변수에 원시 값을 할당한 경우
-> 원시값은 변경할 수 없는 값, const 키워드에 의해 재할당 금지
-> 할당된 값 변경 불가
유지 보수의 편의, 상태 유지, 가독성에 유리
여러 단어로 이루어진 경우 _로 구분하여 스네이크 케이스로 표현
// 0.1 세율 상수 표현
// 변수 이름을 대문자로 선언하여 상수임을 나타냄
const TAX_RATE = 0.1;
// 세전 가격
let preTaxPrice = 100;
// 세후 가격
let afterTaxPrice = preTaxPrice + (preTaxPrice * TAX_RATE);
console.log(afterTaxPrice); // => 110
const 키워드와 객체
const 키워드로 선언된 변수에 객체 할당 시 변경 가능
=> const 키워드는 재할당을 금지할 뿐 프로퍼티 동적 생성, 삭제, 프로퍼티 값의 변화를 통한 객체 변경 가능
(객체가 변경되더라도 변수에 할당된 참조 값은 변경되지 않음)
const person = {
name: 'Lee'
};
// 객체는 변경 가능한 값, 재할당 없이 변경 가능
person.name = 'Kim';
console.log(person); // {name: "Kim"}
15. 4 var vs. let vs. const
ES6을 사용한다면 var 키워드는 사용하지 않는다
재할당이 필요한 경우에만 let 키워드를 사용하며 변수의 스코프는 최대한 좁게 만듬
재할당이 필요없는 원시 값과 객체에는 const 키워드 사용
우선 const 키워드를 사용한 후 변경하는 것이 안전