事隔多年終於開始來補前端的深度了,那就先研究變數宣告:var, let, const 的差別吧。
先講結論:差別在於變數的生命週期
關鍵字 | 作用範圍 | 可修改 |
(無) | 全域 | v |
var | 函式 | v |
let | 區域 | v |
const | 區域 | x |
再來看程式範例
一、全域:不使用關鍵字
沒毛病,一經宣告在所有函式裡都可以引用的,以下範例使用無關鍵字宣告。
改成使用 var 或 let 宣告也是得到一樣的效果,因為 var, let 宣告在最外面,可以當作整個js 都是一個同一個區域,當然作用範圍就在整個js 檔。
但是要注意,如果在區域內宣告無關鍵字變數,外層也沒有宣告過此變數,則雖然他在區域內,但範圍還是會變成全域,如下:
注意到了嗎,既使value1 是宣告在print 方法內部,但因為外面沒有宣告而變成全域變數,所以console.log 也能抓到值 = 50。
另外值得注意的是,如果在第二行將value1 的宣告改為 var 或 let,第八行的console 就會因為變數生命週期的改變跳出 undefined 的例外狀況
二、函式:在function 內宣告
在function 裡面可以再宣告function,而如果子function 裡面有宣告跟外面一樣的變數,會在子function 的範圍內,暫時取代外面的變數。而離開子function 後,又會回復成父function的值。但在function 外面 存取會發生錯誤 (第15行)。
有趣的是,因為範圍是在整個function 中,經過JS 的變數提升Hoisting (在執行之前會先定義好function 內的 var),所以先取用變數也只會顯示undefined。
但將var 改為let 就會直接錯誤,若將let 插入到第二列,或是將print2 移到第九列,一旦經過宣告後,就可以正常執行。
另外一個需要注意的是var 的函式範圍,參考下圖:
number1, number2 都宣告在if 的範圍裡,if 裡面的console.log 可以抓到兩個變數。而跑到if 外面時,宣告為let 的number2 已經結束生命週期,故在if 外面抓不到此變數會產生Error。
三、區域:影響該區域,以外的地方無法存取。
區域的範例也就是上面let number2 的狀況,只要脫離宣告的區域就會結束生命週期,這邊就不測試了。
故結論為:
JavaScript 比較有彈性,與後端的程式語言不同。但若寫程式稍不注意,就可能會影響到外部,產生非預期的結果/錯誤。
盡量使用let 並依照後端的習性來宣告、使用變數,可以降低意外的發生。
References:
https://tw.alphacamp.co/blog/javascript-var-let-const
https://www.w3schools.com/js/js_let.asp