深刻理解ES6之let與const

上個月本身花了 1300 買了阿(a)裏(li)的 服 務 器來學習 node 及對應的框架,在 11 號以前它們有作活動,1300 的配置如今一年只要 86 元,三年只要229元,真心以爲很划算了,能夠點擊本條內容進行參與javascript

1 爲何ES6要引入let和const(var命令所存在的問題)

1.1 變量提高

if (false) {
  var a = 1
}
console.log(a)
複製代碼

正常理解上,if語句斷定爲false,var a = 1不會執行,最後 console.log(a)應該會報錯纔對,但實際結果爲undefined。 致使這個結果的緣由就是變量提高,上述代碼能夠理解爲java

var a
if (false) {
  a = 1
}
console.log(a) // undefined
複製代碼

這樣結果就顯而易見了。node

1.2 沒有塊級做用域

一個老生常談的面試題、面試

var funcs = []
for (var i = 0; i < 3; i++) {
  funcs[i] = function () {
    console.log(i);
  };
}
funcs[0]() // 3
複製代碼

由於沒有塊級做用域,因此 i 泄漏爲全局變量,funcs數組中方法所引用的變量 i 都是這一全局變量,致使函數並無如預想的方式對變量i進行輸出 0 1 2數組

1.3 能夠重複聲明

var a = 1
var a = 2
console.log(a) // 2
複製代碼

變量能夠被重複的聲明,可能會致使程序產生意想不到的bug框架

1.4 在全局做用域中聲明的變量會建立爲全局變量做爲全局對象的屬性

var a = 1
console.log(window.a) // 1
複製代碼

2 let和const與var的區別

引入let和const就是爲了解決上述var所存在的問題,這也就二者之間的區別函數

  • 不會進行變量提高
  • 塊級做用域
  • 不能夠重複聲明
  • 不會建立爲全局對象的屬性

可使用上面的例子進行檢測學習

3 let和const之間的區別

3.1 let聲明的變量能夠從新賦值,const聲明的則不能夠,因此const在聲明變量時就必定要進行初始化

let a = 1
a = 2 // 2
const b = 1
b = 2 // Uncaught TypeError: Assignment to constant variable.
複製代碼

const聲明不容許從新賦值,並非變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動,但容許修改值。這意味着當用const聲明對象時,對象的修改就是不可控的了ui

const obj = {
  propName: 1
}
obj.propName = 2 // 2 這樣是徹底能夠的
複製代碼

4 暫時性死區

letcosnt聲明的變量,在聲明以前,該變量都是不可用的,這在語法上,稱爲「暫時性死區」(temporal dead zone,簡稱 TDZ)spa

var a = 1
function foo () {
  console.log(a)
  let a = 2
}
foo() // Uncaught ReferenceError: a is not defined
複製代碼

這段代碼,按照let聲明的變量不會進行變量提高理解時,foo方法中console.log(a)應該查找到全局的變量a,打印出2纔對。爲何會報錯呢? 這就是由於暫時性死區 JavaScript 引擎在掃描代碼發現變量聲明時,要麼將它們提高到做用域頂部(遇到 var 聲明),要麼將聲明放在 TDZ 中(遇到 let 和 const 聲明)。訪問 TDZ 中的變量會觸發運行時錯誤。只有執行過變量聲明語句後,變量纔會從 TDZ 中移出,而後方可訪問。因此在聲明foo方法時,函數內部的a已經被放到TDZ中,在未執行聲明語句前使用都會報錯。 上面的代碼段也能夠理解爲只要塊級做用域內存在let const命令,它所聲明的變量就「綁定」(binding)這個區域,再也不受外部的影響

5 總結

let 和 const 的出現解決了 var 聲明變量時存在的一系列問題,因此目前的最佳實踐是:默認使用 const,只有當確實須要改變變量的值的時候才使用 let。這是由於大部分的變量的值在初始化後不該再改變,而預料以外的變量值的改變是不少 bug 的源頭。

相關文章
相關標籤/搜索