var 支援 Hoisting, 因此可在執行之後才使用 var 宣告 variable 與 function;但 let 不支援 Hoisting,只能在執行前先宣告好,因為 var 在 JavaScript Engine 的 Creation Phase 已經將 Variable 與 Function 建立完成。
Version
ECMAScript 5
var
console.log(name)
foo()
var name = 'Sam'
function foo() {
console.log('foo')
}
name 與 foo() 都在執行後才宣告。

實際執行發現 name 為 undefined,但 foo() 卻可正常執行,why ?
JavaScript engine 在執行時分兩個時期:
- Creation Phase
- Execution Phase
在 creation phase 時,JavaScript engine 會將所有 variable 與 function 都載入 memory,無論 variable 或 function 宣告在實際執行程式之前或之後。
因此 name 與 foo() 都會先載入 memory。
此時 name 為 undefined,foo() 則為完整 function 定義。
因此 console.log(name) 印出 undefined,foo() 可印出 foo。
name 將在 console.log() 與 foo() 執行完後才會指定為 Sam。
var name = 'Sam'
console.log(name)
foo()
function foo() {
console.log('foo')
}
若要正確印出 Sam,則必須在 console.log() 之前執行 var name = 'Sam'。
如此 creation phase 雖然 name 為 undefined,但 execution phase 隨即將 name 指定為 Sam,因此可正常印出 Sam。

let
console.log(name)
foo()
let name = 'Sam'
let foo = function() {
console.log('foo')
}
若由 var 改用 ES6 的 let,則直接 runtime error。
因為 let 並不支援 hoisting,不會在 creation phase 建立 variable 與 function,因此不可在執行後才使用 let 宣告 variable 與 function。

let name = 'Sam'
console.log(name)
let foo = function() {
console.log('foo')
}
foo()
name 與 foo() 必須在執行前先使用 let 宣告後方可正常執行。

Conclusion
- 只有
var才支援 hoisting,let沒有支援 var的 hoisting 是因為 variable 與 function 在 creation phase 已經完成配置,其中 variable 為undefined,function 則包含完整定義,variable 必須在 execution phase 才會定義初始值