詳解ES6(一) - 區別var、let和const實現塊級作用域

ES6之前的JavaScript變量由var聲明,而var聲明的變量是始終保存在內存中的,爲了實現塊級作用域,我們會使用閉包模擬,但實際上非常的不方便。ES6添加了let和const標識符,彌補了這些不足。

var和閉包

我們先來了解一下var和閉包,下面用花括號生成一個塊級作用域,在其內創建變量count:

{
	var count = 5;
}
console.log(count);//5

我們可以看到在塊級作用域外部仍然可以訪問count變量。實際上這段代碼等效爲:

var count;
{
	count = 5;
}
console.log(count);//5

這就是說,變量count的聲明被提升至函數頂部,而初始化操作仍舊留在原初執行。

如果想要模擬塊級作用域,實際上我們要做的是在使用變量的時候爲其賦值塊級作用域的值。利用函數的特性(可以參考這裏理解),再來看一下閉包:

(function(){
	var count = 5;
	console.log(count);//5
})();
console.log(count);//報錯,count未定義

之所以如此,是因爲函數過程是動態執行的,因此在函數內的變量是動態創建的。

let和const

ES6之後就不需要這麼麻煩了,可以看下面這個例子:

{
	let count = 5;
	console.log(count);//5
}
console.log(count);//報錯

總結一下,let和const聲明的變量都是塊級作用域,在塊級作用域之外訪問就會報錯

此外,他們還有另一個特性,那就是不允許重定義,像下面這樣就會報錯:

var value = 30;
let value = 2;//報錯,不能重複定義

const與let的區別在於:const必須初始化且只能初始化一次,若改變變量值就會報錯。此外,const變量如果是對象,對象的屬性可以修改。

另外我們需要注意一個特性,看下面的例子:

if(condition){
    console.log(typeof value);//引用錯誤
    let value = "blue";
}

但是這樣寫就不會報錯:

console.log(typeof value);//"undeined"
if(condition){
    let value = "blue";
}

循環中的塊作用域綁定

看下面的例子:

for(var i=0;i<10;i++){
	console.log(i);//0...9
}
console.log(i);//10
for(let i=0;i<10;i++){
	console.log(i);//0...9
}
console.log(i);//報錯
for(const i=0;i<10;i++){
	console.log(i);//輸出0後報錯,因爲const不能改變
}
console.log(i);//報錯

但是const可以用在for-in或for-of中,不會報錯,如下。

var obj = {a:true,b:true,c:true}
for(const key in obj){
	console.log(key);//a/b/c
}

全局塊作用域綁定

當var被用於全局作用域時,它會創建一個新的全局變量作爲全局對象(瀏覽器環境中的window對象)的屬性。這樣就有可能會出現下面的錯誤。

//在瀏覽器中
var RegExp = "Hello!";
console.log(window.RegExp );//"Hello!"

但使用let就不會出現這種錯誤。

//在瀏覽器中
let RegExp = "Hello!";
console.log(RegExp );//"Hello!"
console.log(window.RegExp === RegExp);//false

最後建議:默認使用const,只有確實需要修改變量時使用let。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章