var : var的作用域是屬於"函式作用域(Function Scope)"意思是當我們在一個函數內部用 var 宣告變數時,變數只在該函數內部可見,是可以被重複宣告的,是使用在變數可能或不會被重新賦予值,或者宣告範圍在整個函式(function)或者區塊(block)中,但是跟let相比之下,比較不嚴僅,如果後面程式碼一多可能會導致程式碼難以維護。
例子:
if(true){
var a = "ccccc"
}
console.log(a)

我們透過上述程式碼的範例中,即便var變數是在if裡面的區塊被宣告的,但是他仍然可以在區塊外部看見。因為var沒有所謂的"區塊作用域"。
var可以重複宣告:
var a = "apple"
var a = "banana"
console.log(a)
let b = "111"
let b = "222"
console.log(b)

執行出來之後就會像這樣子,var宣告過兩次a了,但是系統卻只出現說let宣告的b已經被宣告過了。
但是我們把let拿掉:
var a = "apple"
var a = "banana"
console.log(a)

去執行的結果,會發現系統出現banana,代表var可以重複宣告,也可以重複賦予值。
還有一個var在程式會出現一個很重要的行為:"宣告會被提升到作用域頂部,但賦值不會提升。"
也就說程式執行前的編譯階段,會先把所有的 var 宣告找出來,並且提升到作用愈的最上層(即便程式肉眼上沒有更改,可是系統上會自動做,是肉眼查看不到的)
而「變數的值」不會一起提升,只會只有var被提升而已。而預設值是 undefined。
function外就存取不到變數:
console.log(a)
var a = 10
會出現的結果會是這樣:

這樣撰寫,等於這樣子
var a
console.log(a)
a = 10
這邊不會噴錯,因為變數「宣告」已經存在。
但是改成let或者const,就會噴錯了
console.log(a)
let a = 5

而 var 的作用域規則 = 宣告所在的 function,但它不會被 if、for、while 的 {} 限制。
範例:
if (true) {
var x = 123
}
console.log(x)

但是換成let/const 就會噴錯:
if (true) {
let y = 456;
}
console.log(y)

如果用Function:
function test() {
var a = 10
}
console.log(a)

只有 function 能限制 var 的範圍。
{
var z = 999
}
console.log(z)

執行結果出來只有{}也無法擋住var。
let: let的作用是屬於"區塊作用域(Block Scope)",宣告的方式跟var差不多,但是let不可以重複宣告,但是可以重新賦予值。
範例:
let a = 111
let a = 222
console.log(a)

因為上述程式碼已經使用"let a = 111"了,我們後面再加上"let a = 222"的程式碼去執行,系統會給出我們"a已經被宣告了"的訊息。
但是我們沿用上述寫法去執行:
let a = 111
a = 222
console.log(a)

執行結果會出現222,因為"let"的值可以重新賦予,但是不能重複宣告。
const : 跟let一樣都是屬於"區塊作用域(Block Scope)",但是跟let相比起來是較為嚴謹的宣告方式,需初始化,不可重複宣告,用來宣告不變動的值。
範例:
const a = 111
a = 222
console.log (a)

輸入上述程式碼之後,會出現上述結果,因為const是不變的常數,所以重新賦予值,系統會出現不能賦值的常數錯誤。
正解範例:
const a = 111
console.log (a)

