事實上 var的設計可以看成是js語言設計上的一個錯誤,但是這種錯誤多半不能修復和已出,因爲要前後兼容,大概2008年的時候,Brendan Eich就決定修復這個錯誤,於是他添加了一個新的關鍵詞:let,我們可以將let看成更完美的 var,很多語言在它早期被設計的時候,基於當時歷史的原因,他考慮不到以後可能面臨的問題,所以很多語言都是有缺陷的,比如java,近幾年一直在頻繁的更新,一年更新一個版本甚至兩三個版本,
塊級作用域
js中使用var來聲明一個變量時,變量的作用域主要和函數的定義有關
針對其他快定義來說是沒有作用域的,比如if/for,這在我們開發中往往會遇到一些問題
let和var都是用來定義變量的,但是let是有塊級作用域的,var沒有塊級作用域,
那麼什麼是作用域?? 作用域其實完整叫法應該是變量作用域 ,就是變量在什麼範圍內是可用的,很多語言都是有塊級作用域的,
沒有塊級作用域會引起的問題 if的塊級
var fn;
if (true) {
var name = "kobe"
fn = function() {
console.log(name)
}
}
var name = "james"
fn()
本來你是想打印kobe的,結果你不知道什麼時候在外面重新定義了下name,結果james替換了kobe
沒有塊級作用域會引起的問題 for的塊級
var btns = document.getElementsByTagName("button");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
console.log(i)
})
}
函數裏面的i一直是引用的外面的i 而外面的i是一直在改變的,點擊第一個按鈕的時候你其實希望打印的是0 ,但是在你點擊按鈕的時候,已經for循環已經結束了,i已經從0變到1變到2變到3變到4變到5了,
解決辦法1(閉包)
爲什麼閉包可以解決,因爲函數是一個作用域,函數裏面的i一旦賦值之後,不會被改掉,ES6之前因爲if和for都沒有塊級作用域,所以在很多時候,我們都必須藉助於function的作用域來解決應用外面變量的問題
var btns = document.getElementsByTagName("button");
for (var i = 0; i < btns.length; i++) {
(function(i){
btns[i].addEventListener("click", function() {
console.log(i)
})
})(i)
}
解決辦法2(let)
ES6中 let 可以使if 和 for都具有了塊級作用域
var btns = document.getElementsByTagName("button");
for (let i = 0; i < btns.length; i++) {
(function(i){
btns[i].addEventListener("click", function() {
console.log(i)
})
})(i)
}