[JavaScript] 변수 var, let, const 차이점 및 호이스팅
호이스팅
코드에 선언된 변수 및 함수를 코드 상단으로 끌어올리는 것
* hoist = 건축/건설/화물 운반에 사용되는 장비로, 화물을 끌어올리는 업무 수행
변수가 전역 범위인지, 함수 범위인지에 따라 다르게 수행됨
함수 내에서 선언한 함수 범위(function scope)는 함수의 최상위로
함수 밖에서 선언한 전역 범위(global scope)의 전역 변수는 스크립트 단위의 최상위로 끌어올려진다
최상단으로 끌어 올려지는 건 변수의 선언과 할당 내용을 모두 끌어올리는 것이 아니라
선언만 끌어 올려진다.
즉, 변수 a가 선언되기 전에 console.log를 출력해도 var a 가 최상단으로 끌어올려지면서, 에러가 발생하지않고 undefined를 출력한다.
console.log(a) //undefined
var a = "amy" // var 변수
console.log(a) // amy
//호이스팅 됨
var a;
console.log(a) // undefined
a = "amy"
console.log(a) // amy
SCOPE
변수의 유효범위 혹은 변수 생존범위
1) Global Scope(전역 유효범위)
- 스크립트 전체에서 참조되는 것
2) Local Scope(지역 유효범위)
- 정의된 함수 안에서만 참조, 함수 밖에서는 참조X
변수
1) Global variable(전역 변수)
- 전역에서 선언된 변수, 어디든 참조 가능
2) Local variable(지역 변수)
- 지역(함수) 내에서 선언된 변수이며, 그 지역과 그 지역의 하부 지역에서만 참조 할 수 있음
변수는 선언 위치(전역 또는 지역)에 의해 스코프를 가진다.
전역에서 선언된 변수는 전역 스코프를 갖는 전역 변수
지역(내부)에서 선언된 변수는 지역 스코프를 갖는 지역 변수
자바스크립트는 함수 레벨 스코프(function-level scope)를 따른다.
함수 레벨 스코프란 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다(참조할 수 없다)는 것이다.
단, ECMAScript 6에서 도입된 let keyword를 사용하면 블록 레벨 스코프를 사용할 수 있다.
블록 레벨 스코프란 코드 블록({…})내에서 유효한 스코프
var x = 0;
{
var x = 1;
console.log(x); // 1
}
console.log(x); // 1
let y = 0;
{
let y = 1;
console.log(y); // 1
}
console.log(y); // 0
전역변수 x와 지역변수 x가 중복 선언되었다.
전역 영역에서는 전역변수만이 참조 가능하고 함수 내 지역 영역에서는 전역과 지역 변수 모두 참조 가능하나,
위 예제와 같이 변수명이 중복된 경우, 지역변수를 우선하여 참조한다.
var x = 'global';
function foo() {
var x = 'local';
console.log(x);
}
foo(); // local
console.log(x); // global
그렇다면,
var, let, const의 차이점
1. 변수 선언 방식
- var는 변수 재선언 가능
- let과 const는 변수 재선언 불가능
(// Uncaught SyntaxError: Identifier '~~~' has already been declared)
- let과 const 중, let은 변수에 재할당 가능, const는 변수 재할당 불가능 ( 변수의 immutable 여부 차이 = 불변성?)
let name = 'bathingape'
console.log(name) // bathingape
let name = 'javascript'
console.log(name)
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name) //react
const name = 'bathingape'
console.log(name) // bathingape
const name = 'javascript'
console.log(name)
// Uncaught SyntaxError: Identifier 'name' has already been declared
name = 'react'
console.log(name)
//Uncaught TypeError: Assignment to constant variable.
2. 호이스팅
너무 어려워... 😭 ㅠㅠ
자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅함
하지만,
var 로 선언된 변수와는 달리 let 로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
왜...?
let 로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.
변수는 선언 단계 > 초기화 단계 > 할당 단계 에 걸쳐 생성되는데
var 으로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다
let은 값을 할당하기전에 변수가 선언 되어있어야 하는데 그렇지 않기 때문에 에러가 난다.
// let은 선언하고 나중에 값을 할당이 가능하지만
let dd
dd = 'test'
// const 선언과 동시에 값을 할당 해야한다.
const aa // Missing initializer in const declaration
그렇다면?
변수 선언에는 기본적으로 const를 사용하고, 재할당이 필요한 경우에 한정해 let 을 사용하는 것이 좋다.
그리고 객체를 재할당하는 경우는 생각보다 흔하지 않다.
const 를 사용하면 의도치 않은 재할당을 방지해 주기 때문에 보다 안전하다.
- 재할당이 필요한 경우에 한정해 let 을 사용한다. 이때, 변수의 스코프는 최대한 좁게 만든다.
- 재할당이 필요 없는 상수와 객체에는 const 를 사용한다.
출처: https://velog.io/@bathingape/JavaScript-var-let-const-%EC%B0%A8%EC%9D%B4%EC%A0%90