ES6之聲明

作者原文:http://hawkzz.com/blog/blog/1515483679215

Var聲明和提升機(jī)制

在函數(shù)作用域和全局作用域中通過(guò)關(guān)鍵字var聲明變量,無(wú)論是在哪里聲明,都會(huì)被當(dāng)成在當(dāng)前作用頂部聲明的變量,這就是我們常說(shuō)的變量提升機(jī)制。廢話不多說(shuō),來(lái)看一個(gè)例子:

function getValue(flag){

     if(flag){
        var value = 'abc';
        retun value;
     }else{
        console.log(value);//undefined;
        return null;
     }
}

由上面的例子可以看出,變量value由于變量提升機(jī)制,在哪里都可以被訪問(wèn)到,其實(shí)上面代被解析成一下代碼:

function getValue(flag){
    var value;//變量提升
    
    if(flag){
        value = 'abc';
        retun value;
    }else{
        console.log(value);//undefined;
        return null;
    }
}

塊級(jí)聲明

塊級(jí)聲明用于聲明在指定塊的作用域之外無(wú)法訪問(wèn)的變量;塊級(jí)作用域存在于:

  • 函數(shù)內(nèi)部
  • 代碼塊{}中

let聲明

ES6新增let聲明,用法類似var。用let代替var來(lái)聲明變量,可以將變量的作用域限制在當(dāng)前代碼塊中。

var聲明變量:

var  a = 10;

{
    var a = 20;
}

console.log(a);//20

let聲明變量:

let a = 10;

{
    let a = 20;
}
console.log(a);//10

let也沒(méi)有變量提升機(jī)制,用let聲明的變量不會(huì)在被到作用域頂部;

function getValue(flag){

    if(flag){
        let value = 'abc';
        return value;
    }else{
        console.log(value);//error:value is not defined
        return null;
    }
}

運(yùn)行上面代碼,當(dāng)flag為false時(shí),會(huì)報(bào)錯(cuò);

const聲明

用const聲明一個(gè)只讀的常量,一旦聲明,其值就不可以更改,并且聲明時(shí)必須初始化,否則會(huì)報(bào)錯(cuò);

const a ;//Module build failed: SyntaxError

const PI = 3.1415926;
console.log(PI);//3.1415926

PI = 3;//TypeError

const和let一樣都是塊級(jí)聲明,所以只在當(dāng)前作用域內(nèi)有用,一旦離開(kāi)就會(huì)報(bào)錯(cuò);

{
   const a = 'abc';
}
console.log(a);//error

const的本質(zhì)

實(shí)際上const聲明保證的不是值的不改的,而是變量指向的內(nèi)存地址不得改動(dòng)。對(duì)于簡(jiǎn)單類型的數(shù)據(jù)(Number,String,Boolean),變量保存的就是其內(nèi)存地址,改變其值就是改變其內(nèi)存地址;對(duì)于復(fù)合類型的數(shù)據(jù)(Array,Object),變量保持的不是其內(nèi)存地址,而是指向
內(nèi)存地址的指針,所以復(fù)合類型的數(shù)據(jù)只要保證指針不改動(dòng)就行,至于里面的數(shù)據(jù)結(jié)構(gòu)改變,這個(gè)就不能控制了;

const obj = {};
obj.name = 'Jon';
obj.age = 23;

console.log(obj);//{name: "Jon", age: 23}

obj = {name:1};//error

從上面代碼中,常量obj是個(gè)對(duì)象,所以保存的是一個(gè)指針,當(dāng)增加屬性和刪除屬性時(shí),由于保存的指針沒(méi)有變,所以不會(huì)保存;當(dāng)給其重新賦值的時(shí)候,改變其指針,所以報(bào)錯(cuò);

禁止重復(fù)聲明

如果在同一作用域內(nèi),已經(jīng)存在一個(gè)變量,再使用let或const聲明這個(gè)變量時(shí)會(huì)報(bào)錯(cuò);

{
    var a = 10;
    let a = 10;//報(bào)錯(cuò)
}

在上面例子中,變量a在代碼塊中被聲明了兩次,第一次被var聲明,沒(méi)有任何問(wèn)題,當(dāng)?shù)诙伪籰et聲明時(shí),報(bào)錯(cuò);因?yàn)橐呀?jīng)存在變量a了;

 let a = 10;
    
 {
     let a = 20;//不報(bào)錯(cuò)
 }

上面的例子中,變量a被聲明兩次沒(méi)有報(bào)錯(cuò),因?yàn)檫@次聲明不在同一作用域;

暫時(shí)性死區(qū)(TDZ)

如果區(qū)塊中存在let和const命令,這個(gè)區(qū)塊對(duì)這些命令聲明的變量,從一開(kāi)始就形成了封閉作用域,且let和const聲明的變量不會(huì)被提升到作用域的頂部,如果在聲明之前使用這些變量,就會(huì)報(bào)錯(cuò)。

if(true){
    console.log(tmp);//報(bào)錯(cuò)
    
    let tmp = 'abc';
}

由于console.log(tmp);語(yǔ)句會(huì)拋出錯(cuò)誤,因此用let定義并初始化變量的語(yǔ)句不會(huì)執(zhí)行,此時(shí)就會(huì)稱為:“暫時(shí)性死區(qū)”(簡(jiǎn)稱:TDZ);所以在使用變量之前,都需要聲明變量;

全局作用域綁定

let和const與var的另一個(gè)區(qū)別是它們?cè)谌肿饔糜蛑械男袨?。?dāng)var被用于全局作用域時(shí),它會(huì)創(chuàng)建一個(gè)新的全局變量作為全局對(duì)象的屬性;

var str = 'Hello';
console.log(window.str);//Hello

如果在全局作用域中使用let或const,會(huì)在全局作用域下創(chuàng)建一個(gè)新的綁定,但該綁定不會(huì)添加為全局對(duì)象的屬性;

let str = 'Hello';
console.log(str);//Hello
console.log(window.str);//undefined
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容