hoisting
스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 행동한다.
스코프 단위로 hoisting 한다.
var, function 그리고 import 까지도 호이스팅 된다.

var
한번 선언된 변수를 다시 선언할 수 있다.

var name = 'malza';
console.log(name);
var name = 'moon';
console.log(name);
//위의 경우가 가능하다.

let name = 'malza';
console.log(name);
let name = 'moon';
console.log(name);
//에러가 발생한다.

선언하기 전에 사용할 수 있다.
console.log(malza);  //  undefined
var malza = 'malza';
//사용 된다. 그런데 undefined 가 출력된다. 왜 그럴까?
//이는 hoisting 의 특징인데, 실제로 var 변수를 맨 위로 끌어올리지는 않지만, 맨 위로 끌어올려진 것처럼 동작해서 선언하기도 전에 사용이 되는 것이다.
//그렇지만 할당은 맨 위로 끌어올려지지 않는다. 그렇기 때문에 undefined 가 나온다.

console.log(malza);
let malza = 'malza';
// let 은 error 가 난다. let은 hoisting 되지 않는 것일까? 사실은 let 과 const 또한 hoisting 이 이뤄진다. 그렇다면 왜 error 가 나는 것일까?
// 그 이뉴는 Temporal Dead Zone 때문이다.
// let 과 const 는 TDZ 의 영향을 받는다. 할당을 하기 전에는 사용 할 수 없게 된다. 이는 코드를 예측 가능하게 하고, 잠재적인 bug를 줄일 수 있다.
TDZ 는 선언문이 존재하는 스코프 범위 안에서 변수에 영향을 준다.

fuction somethigFunc(something){ --> 외부 함수 스코프 (TDZ 존을 기준으로)
	typeof variable; // undefined
	if(something){  --> 내부 블록 스코프
		typeof variable;
		let variable; // 이걸 선언하는 순간 위의 typeof vaiable 은 TDZ 존에 의해서 ReferenceError 를 throw 한다.
	}
}
변수의 생성 과정

1. 선언 단계
2. 초기화 단계
3. 할당 단계

var 는 선언 및 초기화(undefined 를 할당)가 동시에 된다. 그래서 선언하지 않고 사용하게 되면 undefined가 나오는 것.

let 은 선언 단계와 초기화 단계가 따로 있다. hoisting 되면서 선언이 이루어 지지만 초기화 단계는 실제로 코드에 도달해야 한다.

const 는 선언과 할당이 동시에 되어야 한다.
스코프

var : 함수 스코프 (function-scoped)
블록 스코프 { } 내에서 사용 했더라도 외부에서 사용 가능하다. 단!
함수 내에서 사용 된다면 얘기가 다르다. 사용할 수 없다.
function add(num, num2) {
	var result = num + num2;
}
console.log(result); // error!

let, const : 블록 스코프 (block-scoped)
블록 코스프는 { } 내에서 선언된 변수는 해당 코드 블록 내에서만 유효하며 외부에서는 접근 할 수 없다. 즉 지역변수!

var 의 사용을 권장하지 않는다. 많은 위험성을 가지고 갈 필요는 없다. let 과 const 의 사용을 권장한다.