var、let袱院、const區(qū)別

一屎慢、var聲明的變量會(huì)掛載在window上,而let和const聲明的變量不會(huì)

var a =100;

console.log(a,window.a); // 100 100

let b =10;

console.log(b,window.b);// 10 undefined

const c =1;

console.log(c,window.c);// 1 undefined

二忽洛、var聲明變量存在變量提升腻惠,let和const不存在變量提升

console.log(a);// undefined? ===>? a已聲明還沒(méi)賦值,默認(rèn)得到undefined值

var a =100;

console.log(b);// 報(bào)錯(cuò):b is not defined? ===> 找不到b這個(gè)變量

let b =10;

console.log(c);// 報(bào)錯(cuò):c is not defined? ===> 找不到c這個(gè)變量

const c =10;

三欲虚、let和const聲明形成塊作用域集灌,而var不存在此作用域

if(true){

var a =100;

letb =10;

const c =1;

}

console.log(a);// 100

console.log(b)// 報(bào)錯(cuò):b is not defined? ===> 找不到b這個(gè)變量

console.log(c)// 報(bào)錯(cuò):c is not defined? ===> 找不到c這個(gè)變量

注:var聲明的變量屬于全局變量,可以修改复哆,可以聲明相同名字的變量绝页,let、const不可以寂恬,只能在作用域內(nèi)使用

ES6之let(理解閉包)和const命令

  最近做項(xiàng)目的過(guò)程中续誉,使用到了ES6,因?yàn)橹昂苌俳佑|初肉,所以使用起來(lái)還不夠熟悉酷鸦。因此購(gòu)買了阮一峰老師的ES6標(biāo)準(zhǔn)入門,在此感謝阮一峰老師的著作牙咏。

  我們知道臼隔,ECMAScript 6即ES6是ECMAScript的第五個(gè)版本,因?yàn)樵?015年6月正式發(fā)布妄壶,所以又成為ECMAScript2015摔握。ES6的主要目的是為了是JS用于編寫復(fù)雜的大型應(yīng)用程序,成為企業(yè)級(jí)的開發(fā)語(yǔ)言丁寄。

說(shuō)明:由于有時(shí)候我們希望得知es6代碼的具體實(shí)現(xiàn)原理或者說(shuō)希望能夠轉(zhuǎn)化為es5使用氨淌,我們可以使用http://babeljs.io/來(lái)實(shí)現(xiàn)在線將es6代碼轉(zhuǎn)化為es5代碼。

第一部分:let命令

  一.塊級(jí)作用域(重點(diǎn))伊磺。

   我們知道盛正,在javascript中只有全局作用域和函數(shù)作用域,并不存在塊級(jí)作用域屑埋。這樣豪筝,在使用時(shí)就會(huì)出現(xiàn)一些問(wèn)題。 下面我們先來(lái)舉例說(shuō)明let塊級(jí)作用域的使用。

   例1:

  代碼如下所示:

? ? ? ? {

? ? ? ? ? ? vara=5;

? ? ? ? ? ? let b=10;

? ? ? ? }

? ? ? ? console.log(a);

? ? ? ? console.log(b);

  我們?cè)诳刂婆_(tái)得到的結(jié)果如下所示:

  也就是說(shuō)续崖,var聲明的變量由于不存在塊級(jí)作用域所以可以在全局環(huán)境中調(diào)用敲街,而let聲明的變量由于存在塊級(jí)作用域所以不能在全局環(huán)境中調(diào)用。

 例2:這個(gè)例子是一個(gè)非常經(jīng)典的例子严望。

vara=[];

? ? ? ? for(vari=0;i<10;i++){

? ? ? ? ? ? a[i]=function(){

? ? ? ? ? ? ? ? console.log(i);

? ? ? ? ? ? };

? ? ? ? }

? ? ? ? a[6]();//10? ?

vara=[];

? ? for(let i=0;i<10;i++){

? ? ? ? a[i]=function(){

? ? ? ? ? ? console.log(i);

? ? ? ? };

? ? }

? ? a[6]();//6? ?


我們可以看到聪富,兩個(gè)例子中,唯一的區(qū)別是前者for循環(huán)中使用var來(lái)定義i著蟹,得到的結(jié)果是10.而后者使用的是let來(lái)定義i,最終得到的結(jié)果是6.這是為什么呢梢莽?阮一峰老師在書中的解釋并不是很清楚萧豆,所以下面我會(huì)發(fā)表個(gè)人見解:

關(guān)于這個(gè)問(wèn)題,表面上確實(shí)不是很好理解昏名,查詢了很多資料涮雷,許多人講到了很多晦澀難懂的知識(shí),似乎很高大上轻局,但是實(shí)際上并不難洪鸭,下面根據(jù)我的理解進(jìn)行解釋,如有問(wèn)題仑扑,歡迎批評(píng)指正览爵,如果大家能夠有些收獲就再好不過(guò)了。



例二前者(var i)具體執(zhí)行過(guò)程如下:

var a=[];

var i=0;//由于var來(lái)聲明變量i镇饮,所以for循環(huán)代碼塊不具備塊級(jí)作用域蜓竹,因此i認(rèn)為是全局變量,直接放在全局變量中储藐。

a[0]=function(){

console.log(i);//這里之所以i為i而不是0俱济;是因?yàn)槲覀冎皇嵌x了該函數(shù),未被調(diào)用钙勃,所以沒(méi)有進(jìn)入該函數(shù)執(zhí)行環(huán)境蛛碌,i當(dāng)然不會(huì)沿著作用域鏈向上搜索找到i的值。

}// 由于不具備塊級(jí)作用域辖源,所以該函數(shù)定義就是全局作用域蔚携。

var i=1;//第二次循環(huán),這時(shí)var i=1;覆蓋了前面的var i=0克饶;即現(xiàn)在i為1;

a[1]=function(){

console.log(i);//解釋同a[0]函數(shù)浮梢。

}

var i=2;// 第三次循環(huán),這時(shí) i=2彤路,在全局作用域中秕硝,所以覆蓋了前面的i=1;

a[2]=function(){

console.log(i);

}

......第四次循環(huán) 此時(shí)i=3這個(gè)以及下面的i不斷的覆蓋前面的i,因?yàn)槎荚谌肿饔糜蛑?/p>

......第五次循環(huán) 此時(shí)i=4

......第六次循環(huán) 此時(shí)i=5

......第七次循環(huán) 此時(shí)i=6

......第八次循環(huán) 此時(shí)i=7

......第九次循環(huán) 此時(shí)i=8

var i=9;

a[9]=function(){

console.log(i);

}

var i=10;// 這時(shí)i為10,因?yàn)椴粷M足循環(huán)條件远豺,所以停止循環(huán)奈偏。

緊接著在全局環(huán)境中繼續(xù)向下執(zhí)行。

a[6]();//這時(shí)調(diào)用a[6]函數(shù)躯护,所以這時(shí)隨即進(jìn)入a[6]函數(shù)的執(zhí)行環(huán)境惊来,即a[6]=function(){console.log(i)};執(zhí)行函數(shù)中的代碼 console.log(i); 因?yàn)樵诤瘮?shù)執(zhí)行環(huán)境中不存在變量i,所以此時(shí)會(huì)沿著作用域鏈向上尋找(可參考我的博文《深入理解作用域和作用域鏈》)棺滞,即進(jìn)入了全局作用域中尋找變量i,而全局作用域中i=10覆蓋了前面所有的i值裁蚁,所以說(shuō)這時(shí)i為10,那么a[6]的值就是10了继准。

  

說(shuō)明:對(duì)于例如a[1]=function(){console.log(i)}枉证;而不是a[1]=function{console.log(1)},可以在控制臺(tái)中輸出a[1]函數(shù)移必,即可得到驗(yàn)證室谚。



例二后者(let i)具體執(zhí)行過(guò)程如下:


var a=[];//創(chuàng)建一個(gè)數(shù)組a;

{ //進(jìn)入第一次循環(huán)

let i=0; //注意:因?yàn)槭褂胠et使得for循環(huán)為塊級(jí)作用域,此次let i=0在這個(gè)塊級(jí)作用域中崔泵,而不是在全局環(huán)境中秒赤。

a[0]=function(){

console.log(i);

}; //注意:由于循環(huán)時(shí),let聲明i,所以整個(gè)塊是塊級(jí)作用域憎瘸,那么a[0]這個(gè)函數(shù)就成了一個(gè)閉包入篮。

}//?聲明:?我這里用{}表達(dá)并不符合語(yǔ)法,只是希望通過(guò)它來(lái)說(shuō)明let存在時(shí)幌甘,這個(gè)for循環(huán)塊是塊級(jí)作用域崎弃,而不是全局作用域。


講道理含潘,上面這是一個(gè)塊級(jí)作用域饲做,就像函數(shù)作用域一樣,函數(shù)執(zhí)行完畢遏弱,其中的變量會(huì)被銷毀盆均,但是因?yàn)檫@個(gè)代碼塊中存在一個(gè)閉包,閉包的作用域鏈中包含著(或著說(shuō)是引用著)塊級(jí)作用域漱逸,所以在閉包被調(diào)用之前泪姨,這個(gè)塊級(jí)作用域內(nèi)部的變量不會(huì)被銷毀。(更多閉包知識(shí)饰抒,可以看我的博文《JavaScript之閉包》)

{ //進(jìn)入第二次循環(huán)

let i=1; //注意:因?yàn)閘et i=1; 和?上面的let i=0;出在不同的作用域中肮砾,所以兩者不會(huì)相互影響。

a[1]=function(){

console.log(i);

}; //同樣袋坑,這個(gè)a[i]也是一個(gè)閉包

}

......進(jìn)入第三次循環(huán)仗处,此時(shí)其中l(wèi)et i=2;

......進(jìn)入第四次循環(huán),此時(shí)其中l(wèi)et i=3;

......進(jìn)入第五次循環(huán),此時(shí)其中l(wèi)et i=4;

......進(jìn)入第六次循環(huán)婆誓,此時(shí)其中l(wèi)et i=5;

......進(jìn)入第七次循環(huán)吃环,此時(shí)其中l(wèi)et i=6;

......進(jìn)入第八次循環(huán),此時(shí)其中l(wèi)et i=7;

......進(jìn)入第九次循環(huán)洋幻,此時(shí)其中l(wèi)et i=8;

{//進(jìn)入第十次循環(huán)

let i=9;

a[i]=function(){

console.log(i);

};//同樣郁轻,這個(gè)a[i]也是一個(gè)閉包

}

{

let i=10;//不符合條件,不再向下執(zhí)行文留。于是這個(gè)代碼塊中不存在閉包好唯,let i=10;在這次循環(huán)結(jié)束之后難逃厄運(yùn),隨即被銷毀燥翅。

}

a[6]();//調(diào)用a[6]()函數(shù)骑篙,這時(shí)執(zhí)行環(huán)境隨即進(jìn)入下面這個(gè)代碼塊中的執(zhí)行環(huán)境:funcion(){console.log(i)};

{?

let i=6;?

a[6]=function(){

console.log(i);

}; //同樣,這個(gè)a[i]也是一個(gè)閉包

}

? ? a[6]函數(shù)(閉包)這個(gè)執(zhí)行環(huán)境中权旷,它會(huì)首先尋找該執(zhí)行環(huán)境中是否存在 i,沒(méi)有找到贯溅,就沿著作用域鏈繼續(xù)向上到了其所在的代碼塊執(zhí)行環(huán)境拄氯,找到了i=6,于是輸出了6,即a[6]();的結(jié)果為6它浅。這時(shí)译柏,閉包被調(diào)用,所以整個(gè)代碼塊中的變量i和函數(shù)a[6]()被銷毀姐霍。


相信大家仔細(xì)看完上面的函數(shù)執(zhí)行的過(guò)程鄙麦,對(duì)let var 塊級(jí)作用域 閉包就有一個(gè)很好的理解了。我認(rèn)為重要的是對(duì)于函數(shù)執(zhí)行過(guò)程的理解镊折!



二.不存在變量提升

這里是說(shuō)使用let不會(huì)像使用var一樣存在一個(gè)變量提升的現(xiàn)象胯府。變量提升是什么呢?在沒(méi)有接觸es6之前我對(duì)此也不清楚恨胚,但是我想大家一定都聽說(shuō)過(guò)函數(shù)聲明提升:函數(shù)聲明來(lái)定義函數(shù)即可實(shí)現(xiàn)函數(shù)聲明提升骂因,這樣,我們可以先調(diào)用函數(shù)赃泡,后聲明函數(shù)寒波;而函數(shù)表達(dá)式方法不會(huì)實(shí)現(xiàn)函數(shù)聲明提升,這樣升熊,如果先調(diào)用函數(shù)俄烁,后聲明函數(shù),則會(huì)拋出錯(cuò)誤<兑啊R惩馈(對(duì)于函數(shù)聲明提升更多知識(shí)可以看我的博文《JavaScript函數(shù)之美~》)。那么可以以此類推,var定義變量:可以先使用卷中,后聲明矛双;而let定義變量:只可先聲明,后使用蟆豫。

例3:

  

varnum1=100;

? ? ? ? console.log(num1);

? ? ? ? let num2=200;

? ? ? ? console.log(num2);

? ? ? ? console.log(i);

? ? ? ? vari=10;

? ? ? ? console.log(j);

? ? ? ? let j=5;

    我們可以看到結(jié)果如下:

即前兩個(gè)都是先聲明后使用议忽,沒(méi)有問(wèn)題。而后兩個(gè)都是先使用十减,后聲明栈幸,用var 聲明的顯示undefined,而 let聲明的直接報(bào)錯(cuò)帮辟。

說(shuō)明:console.log(i);

   var i=10;

實(shí)際上相當(dāng)于:

   ?var i;

   ?console.log(i);

   i=10;

所以會(huì)出現(xiàn)undefined的情況速址。


三.暫時(shí)性死區(qū)

  暫時(shí)性死區(qū)即:只要一進(jìn)入當(dāng)前作用域,所要使用的變量就已經(jīng)存在由驹,但是不可獲取芍锚,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量蔓榄。

例5:


vartmp=123;

? ? if(true){

? ? ? ? tmp="abc";

? ? ? ? let tmp;

? ? }


? ?結(jié)果如下:

也就是說(shuō):雖然上面的代碼中存在全局變量tmp并炮,但是塊級(jí)作用域內(nèi)let又聲明了一個(gè)局部變量tmp,導(dǎo)致后者綁定了塊級(jí)作用域甥郑,所以在let聲明變量前逃魄,對(duì)tmp賦值會(huì)報(bào)錯(cuò)。此即暫時(shí)性死區(qū)澜搅。

  

  注意:ES6規(guī)定暫時(shí)性死區(qū)和不存在變量提升就是為了減少運(yùn)行時(shí)的錯(cuò)誤伍俘,防止在變量聲明前就使用這個(gè)變量,從而導(dǎo)致意料之外的行為勉躺。

  

  暫時(shí)性死區(qū)就是: 只要塊級(jí)作用域內(nèi)存在let癌瘾,那么他所聲明的變量就綁定了這個(gè)區(qū)域,不再受外部的影響饵溅。

  暫時(shí)性死區(qū)即 Temperary Dead Zone柳弄,即TDZ。?

  

? ? ? ?注意:暫時(shí)性死區(qū)也意味著 typeof 不再是一個(gè)百分之百安全的操作概说。 ?如下:

if(true) {

? ? ? console.log(typeof x);

? ? ? let x;

? ? }

  這里如果沒(méi)有l(wèi)et x碧注,那么typeof x的結(jié)果是 undefined,但是如果使用了let x糖赔,因?yàn)閘et不存在變量提升萍丐,所以這里形成了暫時(shí)性死區(qū),即typeof x也是會(huì)報(bào)錯(cuò)的放典。逝变。基茵。 ?從這里可以理解暫時(shí)性死區(qū)實(shí)際上就是這一部分是有問(wèn)題的 。




四.不允許重復(fù)聲明

  

function func (){

? ? ? ? let b=100;

? ? ? ? varb=10;

? ? }

? ? function add(num){

? ? ? ? let num;

? ? ? ? returnnum+1;

? ? }

? ? function another(){

? ? ? ? let a=10;

? ? ? ? let a=5;

? ? }

上述三個(gè)得到的結(jié)果均為:

只是前兩者為 b和num被聲明過(guò)了壳影。注意:第二個(gè)函數(shù)拱层,雖然我們沒(méi)有明確的聲明,但是參數(shù)實(shí)際上是相當(dāng)于用var聲明的局部變量宴咧。




第二部分:const命令

什么使const命令呢根灯?實(shí)際上它也是一種聲明常量的方式。const命令用來(lái)聲明常量掺栅,一旦聲明烙肺,其值就不能改變。初次之外氧卧,const和let十分相似桃笙。也就是說(shuō)前者是用于聲明常量的,后者是用于聲明變量的沙绝。


    1.const聲明常量搏明,一旦聲明,不可改變闪檬。

const a=10;

? ? a=100;

    結(jié)果如下

    2.既然const一旦聲明不可改變星著,所以在聲明時(shí)必須初始化。

const a;

     結(jié)果如下:


    3.const所在的代碼塊為塊級(jí)作用域谬以,所以其變量只在塊級(jí)作用域內(nèi)使用或其中的閉包使用强饮。

if(true){

? ? ? ? const a=10;

? ? }

? ? console.log(a);

    結(jié)果如下:


    4.const聲明的變量不存在變量提升由桌。

if(true){

? ? ? ? console.log(a);

? ? ? ? const a=10;

? ? }

結(jié)果如下:


    5.const不可重復(fù)聲明常量为黎。

vara=10;

? ? const a=5;

結(jié)果如下:

need-to-insert-img



6.const命令只是保證了變量名指向的地址不變,并不保證該地址的數(shù)據(jù)不變行您。

  

need-to-insert-img

const a={};

? ? a.name="zzw";

? ? console.log(a.name);

? ? const b=[];

? ? b.push("zzw");

? ? console.log(b);

? ? const c={};

? ? c={name:"zzw"};

need-to-insert-img

  結(jié)果如下:

need-to-insert-img

因此铭乾,我們使用const所指向的地址不可變,但是地址的內(nèi)容是可以變得娃循。


    7.如果希望將對(duì)象本身凍結(jié)炕檩,可以使用Object.freeze()方法。

const a=Object.freeze({});

? ? a.name="zzw";

? ? console.log(a.name); //undefined

    于是通過(guò)Object.freeze()方法我們就不可以再改變對(duì)象的屬性了(無(wú)效)捌斧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末笛质,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子捞蚂,更是在濱河造成了極大的恐慌妇押,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姓迅,死亡現(xiàn)場(chǎng)離奇詭異敲霍,居然都是意外死亡俊马,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門肩杈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)柴我,“玉大人,你說(shuō)我怎么就攤上這事扩然∷胰澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵与学,是天一觀的道長(zhǎng)彤悔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)索守,這世上最難降的妖魔是什么晕窑? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮卵佛,結(jié)果婚禮上杨赤,老公的妹妹穿的比我還像新娘。我一直安慰自己截汪,他們只是感情好疾牲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著衙解,像睡著了一般阳柔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蚓峦,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天舌剂,我揣著相機(jī)與錄音,去河邊找鬼暑椰。 笑死霍转,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的一汽。 我是一名探鬼主播避消,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼召夹!你這毒婦竟也來(lái)了岩喷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤监憎,失蹤者是張志新(化名)和其女友劉穎纱意,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫虏,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妇穴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年爬虱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腾它。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡跑筝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞒滴,到底是詐尸還是另有隱情曲梗,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布妓忍,位于F島的核電站虏两,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏世剖。R本人自食惡果不足惜定罢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旁瘫。 院中可真熱鬧祖凫,春花似錦、人聲如沸酬凳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宁仔。三九已至稠屠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翎苫,已是汗流浹背权埠。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拉队,地道東北人弊知。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓阻逮,卻偏偏與公主長(zhǎng)得像粱快,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叔扼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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