前言
在JS中,var
早已深入人心,因此本文將不再贅述,僅在必要時拉出來溜溜。
宣告方式 | 變數提升 | 暫時性死區 | 重複宣告 | 可修改值 | 塊級作用域 | 全域性變數屬於頂層物件 |
---|---|---|---|---|---|---|
var | 是 | 否 | 是 | 是 | 否 | 是 |
let | 否 | 是 | 否 | 是 | 是 | 否 |
const | 否 | 是 | 否 | 否(引用型別僅保證地址不被修改) | 是 | 否 |
變數提升
a // a is not defined
let a = 'a'
b // b is not defined
const b = 'b'
c // undefined
var c = 'c'
複製程式碼
暫時性死區
在程式碼塊內,使用let
、const
命令宣告變數之前,該變數都是不可用的。
其本質是,只要一進入當前作用域,所要使用的變數就已經存在了,但是不可獲取,只有等到宣告變數的那一行程式碼出現,才可以獲取和使用該變數。
typeof a // a is not defined
let a = 'a'
typeof b // b is not defined
const b = 'b'
typeof c // "undefined"
var c = 'c'
複製程式碼
以下為幾個比較隱蔽的死區:
-
賦值
var a = a let b = b // b is not defined 複製程式碼
-
函式引數
function foo(a = b, b = 2) { console.log([a, b]) } foo() 複製程式碼
重複宣告
let a = 'a1'
let a = 'a2' // Identifier 'a' has already been declared
a // a1
const b = 'b1'
const b = 'b2' // Identifier 'b' has already been declared
b // b2
var c = 'c1'
var c = 'c2'
c // c2
複製程式碼
修改值
let a = 'a1'
a = 'a2'
a // a2
const b = 'b1'
b = 'b2' // Assignment to constant variable
b // b1
var c = 'c1'
c = 'c2'
c // c2
複製程式碼
const 引用型別僅保證引用地址不可修改
const a = {
a1: 1,
a2: 2
}
a.a3 = 3
a // {a1: 1, a2: 2, a3: 3}
複製程式碼
塊級作用域
{
let a = 'a'
const b = 'b'
var c = 'c'
}
a // a is not defined
b // b is not defined
c // c
複製程式碼
全域性變數不再屬於頂層物件
頂層物件:瀏覽器中指window
,Node中指global
。
let a = 'a'
window.a // undefined
const b = 'b'
window.b // undefined
var c = 'c'
window.c // "c"
複製程式碼
再也不用擔心手抖修改了頂層物件~
解決的問題
-
內層變數覆蓋外層變數;
-
用來計數的迴圈變數變為全域性變數;
- 上面程式碼中,變數j是let宣告的,當前的j只在本輪迴圈有效,所以每一次迴圈的j其實都是一個新的變數,那麼如果每一輪迴圈的變數j都是重新宣告的,那它怎麼知道上一輪迴圈的值,從而計算出本輪迴圈的值?這是因為 JavaScript 引擎內部會記住上一輪迴圈的值,初始化本輪的變數j時,就在上一輪迴圈的基礎上進行計算。
- for迴圈還有一個特別之處,就是設定迴圈變數的那部分是一個父作用域,而迴圈體內部是一個單獨的子作用域。
-
閉包與垃圾回收;
有塊級作用域
無塊級作用域
-
不再需要使用
立即執行函式
,減少程式碼冗餘提升可讀性; -
允許在塊級作用域中宣告函式,函式宣告語句的行為類似於
let
;原來,如果改變了塊級作用域內宣告的函式的處理規則,顯然會對老程式碼產生很大影響。為了減輕因此產生的不相容問題,ES6 在附錄 B裡面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式。
1.允許在塊級作用域內宣告函式。
2.函式宣告類似於var,即會提升到全域性作用域或函式作用域的頭部。
3.同時,函式宣告還會提升到所在的塊級作用域的頭部。
注意,上面三條規則只對 ES6 的瀏覽器實現有效,其他環境的實現不用遵守,還是將塊級作用域的函式宣告當作let處理。
參考
-
你不知道的JavaScript(上)
小結
本文主要介紹了let
、const
與var
定義變數的區別以及優點。推薦我用了兩個月的時間才理解 let這篇文章,供大家思考。
之前宣告變數只能使用var
、function
,現在ES6新增了let
、const
、import
、class
4種方式(import
、class
後續也會一一總結),所以現在總共有6種宣告變數的方式。SO宣告變數,請合理選擇。
感謝閱讀,如有問題,歡迎指正。
最最最最最後,在這四天的五一小長假裡,為大家獻上美景 —— 摩洛哥藍色小鎮??祝大家五一愉快呦~