var、let、const

1.let:聲明變量,有塊級作用域,不允許在同一作用域內(nèi)重復聲明,在不同作用域內(nèi)可以重復聲明,let不像var那樣會發(fā)生“變量提升”現(xiàn)象。所以,變量一定要在聲明后使用,否則報錯。只要塊級作用域內(nèi)存在let命令,它所聲明的變量就“綁定”(binding)這個區(qū)域,不再受外部的影響(稱為暫存死區(qū)),循環(huán)中的let作用域,注意瀏覽器兼容性。
2.var:聲明變量和常量,沒有塊級作用域,var聲明存在變量提升
3.const:聲明一個只讀的常量。一旦聲明,常量的值就不能改變。也可用于聲明對象,數(shù)組。
4.ES6明確規(guī)定,如果區(qū)塊中存在let和const命令,這個區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。
例子:

// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;

// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;
function  test(){
   {
        var  a = 1;
    }
    alert(a); a可以訪問到alert出1
}
function test(){
    {
        let  a = 1;
    }
    alert(a); a不能夠被訪問到alert報錯,因為let具有塊級作用域,只在let 聲明的那個作用域內(nèi)可以訪問
}
function test(){
    {
        let  a = 1;
        let  a = 2;  這樣會報錯在同一作用域下不能重復聲明
    }
    alert(a); a不能夠被訪問到alert報錯,因為let具有塊級作用域,只在let 聲明的那個作用域內(nèi)可以訪問
}
function test(){
    let  a  =  3;
    {
        let  a = 1;
        let  a = 2;  這樣會報錯在同一作用域下不能重復聲明
    }
    alert(a); alert出3
}
function test(){
    let  a  =  3;  會報錯,因為let在同一作用域下不允許重復聲明,而var沒用塊級作用域相當于在這個作用域聲明了a
    {
        var  a = 1;  var沒有塊級作用域相當于在外面聲明了一個a
    }
    alert(a);  
}
function test(){
    var  a  =  3;  不會報錯
    {
        let  a = 1;  這個let聲明的a是在當前這個塊級作用下的a,不受外面作用域下a的沖突影響
    }
    alert(a);  alert出3
}
function test(){
    let  a  =  3;  不會報錯 因為a = 1 聲明在全局 而let a = 3聲明在function test()作用域下
    {
          a = 1;  沒有聲明符聲明相當于在全局聲明了一個a
    }
    alert(a);  alert出3  就近原則  let a = 3 在函數(shù)作用域內(nèi)
}

ps:以上實例所用let聲明的a為常量所以正確應(yīng)該全部改為使用const聲明

對于復合類型的變量,變量名不指向數(shù)據(jù),而是指向數(shù)據(jù)所在的地址。const
命令只是保證變量名指向的地址不變,并不保證該地址的數(shù)據(jù)不變,所以將一個對象聲明為常量必須非常小心。

const foo = {};
foo.prop = 123;
foo.prop// 123
foo = {}; // TypeError: "foo" is read-only

上面代碼中,常量foo儲存的是一個地址,這個地址指向一個對象。不可變的只是這個地址,即不能把foo指向另一個地址,但對象本身是可變的,所以依然可以為其添加新屬性。

const a = [];
a.push('Hello'); // 可執(zhí)行
a.length = 0;    // 可執(zhí)行
a = ['Dave'];    // 報錯

上面代碼中,常量a是一個數(shù)組,這個數(shù)組本身是可寫的,但是如果將另一個數(shù)組賦值給a,就會報錯。

window.a = 1;
a // 1

a = 2;
window.a // 2

頂層對象,在瀏覽器環(huán)境指的是window對象,在Node指的是global對象。ES5之中,頂層對象的屬性與全局變量是等價的。上面代碼中,頂層對象的屬性賦值與全局變量的賦值,是同一件事。
ES6為了改變這一點,一方面規(guī)定,為了保持兼容性,var命令和function
命令聲明的全局變量,依舊是頂層對象的屬性;另一方面規(guī)定,let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性。也就是說,從ES6開始,全局變量將逐步與頂層對象的屬性脫鉤。

var a = 1;
// 如果在Node的REPL環(huán)境,可以寫成global.a
// 或者采用通用方法,寫成this.a
window.a // 1
let b = 1;
window.b // undefined

上面代碼中,全局變量a由var命令聲明,所以它是頂層對象的屬性;全局變量b由let命令聲明,所以它不是頂層對象的屬性,返回undefined。

更詳細參考阮一峰let和const

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容