事實上 var的設計能夠當作是js語言設計上的一個錯誤,可是這種錯誤多半不能修復和已出,由於要先後兼容,大概2008年的時候,Brendan Eich就決定修復這個錯誤,因而他添加了一個新的關鍵詞:let,咱們能夠將let當作更完美的 var,不少語言在它早期被設計的時候,基於當時歷史的緣由,他考慮不到之後可能面臨的問題,因此不少語言都是有缺陷的,好比java,近幾年一直在頻繁的更新,一年更新一個版本甚至兩三個版本,java
塊級做用域
js中使用var來聲明一個變量時,變量的做用域主要和函數的定義有關
針對其餘快定義來講是沒有做用域的,好比if/for,這在咱們開發中每每會遇到一些問題閉包
let和var都是用來定義變量的,可是let是有塊級做用域的,var沒有塊級做用域,ide
那麼什麼是做用域?? 做用域其實完整叫法應該是變量做用域 ,就是變量在什麼範圍內是可用的,不少語言都是有塊級做用域的,函數
沒有塊級做用域會引發的問題 if的塊級設計
var fn; if (true) { var name = "kobe" fn = function() { console.log(name) } } var name = "james" fn()
原本你是想打印kobe的,結果你不知道何時在外面從新定義了下name,結果james替換了kobe
沒有塊級做用域會引發的問題 for的塊級code
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了,blog
解決辦法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) }