javascript 변수 선언 방식의 차이점을 이해하기 위해서는 Hoisting과 Scope의 개념 이해가 필요하다.
자바스크립트에서 스코프란 어떤 변수들에 접근할 수 있는지를 정의한다.
스코프란 전역 스코프와 지역 스코프로 나뉜다.
코드의 모든 범위에서 사용가능
전역 스코프는 변수가 함수 바깥이나 {} 바깥에서 선언되었다면, 전역 스코프로 정의된다.
중괄호로 감싸진 블록 내부에서만 사용이 가능
특정 부분에서 사용이 가능한 변수. 더불어 함수 스코프도 존재한다.
특정함수 내부에서만 사용 가능
함수 내부에서 변수를 선언한다면, 그 변수는 선언한 함수 내부에서만 사용이 가능하다.
const value = 'hello!'; // 글로벌 스코프
function myFunction() {
console.log('myFunction: ');
console.log(value);// output value is undefined
}
function otherFunction() {
console.log('otherFunction: ');
const value = 'bye!'; // 함수 스코프
console.log(value);
}
const value = 'hello!';
function myFunction() {
const value = 'bye!';
if (true) {
const value = 'world';
console.log('block scope: '); // block Scope
console.log(value); // world
}
console.log('function scope: '); //function scope
console.log(value); //bye!
}
myFunction();
console.log('global scope:'); //global scope:
console.log(value); // hello!
const를 var로 교체
var value = 'hello!';
function myFunction() {
var value = 'bye!';
if (true) {
var value = 'world'; // <- 기존 value값에 영향을 미침.
console.log('block scope: '); // block Scope
console.log(value); // world
}
console.log('function scope: '); //function scope
console.log(value); //world!
}
myFunction();
console.log('global scope:'); //global scope:
console.log(value); // hello!
호이스팅이란 자바스크립트에서 아직 선언되지 않은 함수나 변수를 끌어올려서 사용할 수 있도록 하는 자바스크립트의 작동 특성을 말한다.
myFunction();
function myFunction() {
console.log('hello world');
}
선언되지 않은 함수는 자바스크립트가 함수명을 끌어올리는(사전적인 의미로 호이스팅) 특성 덕분에 정상적으로 호출된다. 하지만 호이스팅은 유지보수가 어렵기 때문에 피할 수 있다면 피하자.
console.log(number);
var number = 2; // undefined
자바스크립트가 선언된 number값을 최상단으로 끌어올려 인식해
number는 undefined가 되고, 넘버값이 2가 정의된 것으로 엔진은 인식한다.
함수 선언방식을 const와 let으로 사용하게 될 경우 호이스팅을 방지할 수 있게 된다.
const hoisting = () => {
console.log("First-Name:", name);
var name = "Hodoo";
console.log("Last-Name:", name);
}
hoisting();
// First Name : undefined
// Last Name : Hodoo
// First Name이 undefined인 이유는 지역변수 name이 호이스트 되었기 때문이다.
위 함수를 자바스크립트로 이해하면 다음과 같이 표현할 수 있다.
const hoisting = () => {
var name; // name 변수는 호이스트 되었습니다. 할당은 이후에 발생하기 때문에, 이 시점에 name의 값은 undefined 입니다.
console.log("First name : " + name); // First Name : undefined
name = "Marcus"; // name에 값이 할당 되었습니다.
console.log("Last Name : " + name); // Last Name : Hodoo
}
함수의 선언과 할당의 순서가 뒤바뀌어 있다면 호이스팅에 의해 선언이 상단으로 끌어올려지게되며 TDZ(Temporal Dead Zone)가 생성된다.
함수가 선언되고 할당되기 까지의 공간을 TDZ라고 하고 코드 실행이 변수가 실제 있는 위치에 도달할 때까지 액세스할 수 없기 때문에 레퍼런스 오류가 발생한다 (const와 let은 내부에서 선언된 함수명을 외부에서 접근할 수 없다.)
const TDZ를 실행하기 전에 TDZ에 접근하면, TDZ에 의해 ReferenceError가 발생하게 된다.
// console.log(TDZ);
// output: ReferenceError: tdz is not defined
const TDZ = 'Temporal Dead Zone'
// 위 코드 실행 이후에는 TDZ에 접근할 수 있다.
console.log(TDZ);
// output: Temporal Dead Zone
let/const선언 변수는 호이스팅되지 않는 것이 아니다.
스코프에 진입할 때 변수가 만들어지고 TDZ(Temporal Dead Zone)가 생성되지만, 코드 실행이 변수가 실제 있는 위치에 도달할 때까지 액세스할 수 없는 것이다.(레퍼런스 오류가 발생), 때문에 let/const변수가 선언된 시점과 할당하는 시점을 가깝게 두어서 TDZ를 줄일 수 있도록 코드를 작성해야 한다.
변수의 재할당이 없다면 웬만하면 const를 쓰도록 하자. 낡은 참조문을 보면서 var를 사용하는 것은 반드시 지양해야할 일!