뚜벅

모던 자바스크립트 Deep Dive - 호이스팅, var, let, const 본문

JavaScript

모던 자바스크립트 Deep Dive - 호이스팅, var, let, const

초코맛젤리 2022. 12. 9. 00:14

var, let, const 각각의 특징과 호이스팅에 관해서 정리합니다.

 

var 

- 변수 중복 선언이 가능하다

var a = 'a'
console.log(a) // 'a'

var a = 'aa'
console.log(a) // 'aa'

- 함수 레벨 스코프를 가진다

var 키워드를 사용하여 선언한 변수는 함수 내부에서 선언한 게 아니라면 전역 스코프를 가진 전역 변수이다.

함수 레벨 스코프란?

함수의 코드 블록만을 지역 스코프로 인정하며 함수 외부에서 선언한 변수는 전역 스코프를 가진다.

 

 

- 변수 호이스팅 

var 키워드로 선언한 변수는 호이스팅 과정에서 선언과 초기화가 동신에 진행되며 이때 undefined로 초기화된다.

그렇기 때문에 변수 선언 전에 호출하게 되면 undefined가 출력된다.

console.log(x) // 호이스팅 선언과 동시에 undefined로 초기화 되기 때문에 undefined가 출력된다.

var x = 'global' // 변수 x에 값 'global' 할당

console.log(x) // 'global'

호이스팅이란?

변수 선언문이 스코프의 상단으로 끌어올려지는 것을 의미한다.

 

- 전역 객체 프로퍼티

var 키워드로 선언한 전역 변수, 전역 함수 그리고 선언하지 않은 변수에 값을 할당한 암묵적 전역은 

전역 객체 window의 프로퍼티가 된다.

let, const로 선언한 전역 변수는 window 프로퍼티가 아니다

var x = 'global'
y = 'global' 
function foo(){}

let z = 'global'

console.log(window.x) // 'global'
console.log(window.y) // 'global'
console.log(window.foo) // foo(){}

console.log(window.z) // let, const로 선언한 전역 변수는 window 프로퍼티가 아니다. => undefined

=> 변수의 중복 선언이 가능하고 호이스팅에 의해 가독성을 떨어뜨리고 오류를 발생시킬 여지가 있기 때문에 좋지 않다.

 

let 

var의 단점을 개선하고자 es6부터 새로 생겼다

- 변수 중복 선언이 불가능하다

let x = 'global'
let x = 'error' // SyntaxError: Identifier 'x' has already been declared

 

- 블록 레벨 스코프를 가진다

블록 안에서 let 키워드로 선언한 변수는 모두 지역 스코프를 가지는 지역 변수이다.

let x = 'global' 

{
	let x = 'local'
    let z = 'local'
}

console.log(x) // 'global'
console.log(z) // ReferenceError: z is not defined

function foo(){
	let i = 'foo_local'
    for(let i=0; i<10; i++){
		console.log(i) // 0 ~ 9
    }
    console.log(i) // 'foo_local'
}

블록 레벨 스코프란?

모든 코드 블록(함수, if문, for 문, while 문, try/catch문 등)에서 선언한 변수는 지역 스코프를 가진다.

 

- 변수 호이스팅

let 키워드로 선언한 변수도 호이스팅이 발생하지만 발생하지 않는 것처럼 동작한다. 

이유는 var 키워드로 선언한 변수는 선언과 초기화가 같이 되지만 (undefined)

let 키워드로 선언한 변수는 선언과 초기화 단계가 분리되어 진행되기 때문에 변수 초기화 전에 호출하면 참조 에러가 발생한다.

 

선언단계  x ReferenceError
일시적 사각지대 TDZ
초기화 단계  let x , x = undefined
할당 단계 x = 'global' 

초기화 전에 변수를 호출할 시 참조 에러가 발생하는 것을 일시적 사각지대(TDZ)라고 한다.

 

// x 선언
console.log(x) // ReferenceError: x is not defined => TDZ

let x; // x = undefined 초기화
console.log(x) // undefined 

x = 'global' // 값 할당
console.log(x) // 'global'

=> 재할당 필요한 경우에 사용 

const

let과 대부분 비슷하다. 

 

- 블록 레벨 스코프를 가진다

 

- 선언과 초기화

const는 선언과 초기화를 같이 해야 한다. 

const x = 1 

// Error
const y
y = 1

- 호이스팅

const 키워드로 선언한 변수도 호이스팅이 발생하지 않는 것처럼 동작한다.

 

- 재할당 금지

원시 값을 할당한 경우 변수 값을 변경할 수 없다.

하지만 객체를 할당한 경우 값을 변경할 수 있다. ( 객체는 참조 타입이기 때문에 가능 )

원시 값이란? 

더 이상 쪼갤 수 없는 것으로 number, bigInt, string, null, undefined, boolean, symbol이 있다.

 

=> 의도치 않은 재할당을 방지하기 때문에 조금 더 안전하다.

정리

- es6을 사용한다면 var를 사용하지 않는다.

- 재할당이 필요 없는 원시 값 또는 객체에는 const를 사용하고 재할당이 필요한 경우 let을 사용한다.