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
一個老生常談的面試題、面試
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數組
var a = 1
var a = 2
console.log(a) // 2
複製代碼
變量能夠被重複的聲明,可能會致使程序產生意想不到的bug框架
var a = 1
console.log(window.a) // 1
複製代碼
引入let和const就是爲了解決上述var所存在的問題,這也就二者之間的區別函數
可使用上面的例子進行檢測學習
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 這樣是徹底能夠的
複製代碼
let
與cosnt
聲明的變量,在聲明以前,該變量都是不可用的,這在語法上,稱爲「暫時性死區」(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)這個區域,再也不受外部的影響
let 和 const 的出現解決了 var 聲明變量時存在的一系列問題,因此目前的最佳實踐是:默認使用 const,只有當確實須要改變變量的值的時候才使用 let。這是由於大部分的變量的值在初始化後不該再改變,而預料以外的變量值的改變是不少 bug 的源頭。