详解var、let、const关键词声明变量的区别,以及变量提升、块级作用域的认识等。
首先回顧一下JavaScript中var聲明變量的基礎(chǔ)知識(shí):
? 在使用var關(guān)鍵詞聲明變量時(shí),變量在函數(shù)外則是全局變量,有全局作用域,全局變量在頁(yè)面關(guān)閉后銷毀;變量在函數(shù)內(nèi)則是局部變量,作用局部作用域(變量只能在該函數(shù)內(nèi)有效,函數(shù)執(zhí)行完將自動(dòng)銷毀)
? 我們使用var來(lái)創(chuàng)建變量,聲明后未賦值的變量輸出會(huì)提示 “undefined”。在方法函數(shù)外聲明的變量未使用var ,會(huì)報(bào)錯(cuò)“x is not defined”;
? 在函數(shù)內(nèi)未使用var聲明的變量自動(dòng)變?yōu)槿肿兞?/span>
開發(fā)背景(WHY)為什么要使用let、const關(guān)鍵詞來(lái)創(chuàng)建變量或常量
?解決ES5使用var初始化變量時(shí)會(huì)出現(xiàn)的變量提升問(wèn)題
?解決使用閉包時(shí)出錯(cuò)的問(wèn)題
?解決使用計(jì)數(shù)的for循環(huán)變量時(shí)候會(huì)導(dǎo)致泄露為全局變量的問(wèn)題,
?ES5只有全局作用域和函數(shù)作用域(對(duì)應(yīng)var聲明的全局變量和局部變量時(shí)),沒(méi)有塊級(jí)作用域(ES6中{}中的代碼塊)。同理只能在頂層作用域window中和函數(shù)中聲明函數(shù),不能在塊級(jí)作用域中聲明函數(shù);
那么先來(lái)理解一下什么是變量提升特性,會(huì)導(dǎo)致的問(wèn)題(比如內(nèi)層變量覆蓋外層變量)
?變量初始化時(shí)可以分為兩步:使用關(guān)鍵詞var聲明變量,以及賦值。變量提升就是將聲明變量這一步提升到該作用域的頭部。注意函數(shù)聲明也會(huì)類似var聲明出現(xiàn)提升特效,函數(shù)聲明提升在變量聲明提升上面;
參考網(wǎng)址:https://blog.csdn.net/recoluan/article/details/79253223
實(shí)例01
console.log(foo); console.log(foo2); var foo=2; let foo2=3;
//以上代碼var聲明變量后,相當(dāng)于如下 // var foo; // console.log(foo); //會(huì)提示‘undefined’ // foo=2; // let不存在變量提升,會(huì)報(bào)錯(cuò)
實(shí)例02
var a="我在外面"; function func(){ console.log(a); //undefined console.log(window.a); //我在外面 var a='我在里面'; console.log(a); //我在里面} //以上代碼var聲明變量后,相當(dāng)于如下 // var a="我在外面"; // function func(){ // var a; // console.log(a); // console.log(window.a); // a='我在里面'; // console.log(a); // }
注意:在使用let、const命令聲明的變量不具備變量提升效果;
????:函數(shù)聲明提升會(huì)在變量聲明提升上面
fuc2(); function fuc2(){ console.log(b); //undefined} var b=35; //相當(dāng)于 // function fuc2(){ // console.log(b); // } // var b; // func2(); // b=35;
為什么需要塊級(jí)作用域?
??用來(lái)計(jì)數(shù)的循環(huán)變量泄露為全局變量,如下:
for (var i = 0; i < s.length; i++) { console.log(s[i]); //會(huì)將字符串拆分為一個(gè)個(gè)的字符輸出}console.log(i); // 5? let和const是ES6新增特性,都可生成塊級(jí)作用域(是指聲明在花括號(hào)內(nèi)的變量只在該區(qū)域內(nèi)有效)。let用來(lái)聲明變量,const用來(lái)聲明常量(不可修改變量值,數(shù)組和對(duì)象除外);如果區(qū)塊內(nèi)存在let或const命令,這個(gè)區(qū)塊對(duì)這些命令聲明的變量會(huì)形成封閉的區(qū)域,該區(qū)域外不能被使用,且變量聲明前使用變量會(huì)報(bào)錯(cuò)(又叫暫時(shí)性死區(qū)),更加嚴(yán)謹(jǐn)
var tmp = 123;if (true) { tmp = 'abc'; // ReferenceError,不能未聲明前使用這就是暫時(shí)性死區(qū) console.log(temp); let tmp; temp=666; console.log(temp);}塊級(jí)作用域外不能訪問(wèn)該區(qū)塊內(nèi)的變量或者常量,子塊級(jí)作用域可以訪問(wèn)父塊級(jí)作用域的變量
{ const ss=99;{ console.log(ss); //可以在子塊內(nèi)訪問(wèn)父塊定義的常量}}console.log(ss); //b不可以在塊作用外訪問(wèn)let、const定義的變量或者常量以上代碼中通過(guò)將let替換var就可以修復(fù)各種bug,所以,“let是更完美的var”。
其他的let、const和var的用法及注意點(diǎn)
? let和var的區(qū)別:let聲明的變量只在其聲明的塊或子塊中可用,而var聲明的變量的作用域是整個(gè)封閉函數(shù)可用;
? let和const的特點(diǎn):
① let和const關(guān)鍵詞聲明的變量不具備變量提升的特效(第二步提到了的),存在暫時(shí)性的死區(qū),只能在聲明的位置后使用,同一塊級(jí)作用域中不能反復(fù)聲明同一變量名(子塊級(jí)可以重復(fù)聲明父塊級(jí)變量),var可以;
② let和const聲明只在最靠近的一個(gè)塊(花括號(hào)內(nèi))中有效;
③ 使用const聲明常量時(shí)候大寫,const在聲明時(shí)必須賦值;
注意1: const聲明的變量值并不是不能變的,而是變量指向的內(nèi)存地址是不能變的,對(duì)于數(shù)值、字符串等簡(jiǎn)單類型的數(shù)據(jù),值就保存在變量指向的內(nèi)存地址上,因此等同于常量;但對(duì)于符合類型的數(shù)據(jù)(如數(shù)組和對(duì)象),變量指向的內(nèi)存地址是一個(gè)指引,數(shù)據(jù)結(jié)構(gòu)是否可變就不能控制了,所以將對(duì)象聲明為常量必須非常小心;
const newArr=[23,43,22,66];newArr[0]=888;console.log(newArr); //[888, 43, 22, 66]注意2:外層塊作用域不可以訪問(wèn)塊內(nèi)層作用域,內(nèi)層塊作用域可以獲取外層塊作用域變量,子塊可以重復(fù)定義外層塊作用域變量。函數(shù)在塊級(jí)作用域中聲明是行為類似let,不能被作用域外訪問(wèn),塊中的函數(shù)聲明存在變量提升,確實(shí)需要時(shí)候使用函數(shù)表達(dá)式的形式,而不是函數(shù)聲明語(yǔ)句形式;
function f() { console.log('I am outside!'); }(function () { if (false) { //函數(shù)提升后,這里重復(fù)聲明了該匿名函數(shù)外的函數(shù)f,所以會(huì)覆蓋外部函數(shù) function f() { console.log('I am inside!'); }} f();}());
注意3: ?Let不允許在相同作用域中使用與其他let或const,重復(fù)聲明同一個(gè)變量,所以不能在有參函數(shù)聲明中重復(fù)聲明函數(shù)參數(shù),如function func(arg){let arg}會(huì)報(bào)錯(cuò)
var message = "Hello!";let age = 25;// 以下兩行都會(huì)報(bào)錯(cuò)const message = "Goodbye!";const age = 30;注意4: 在ES5中頂層對(duì)象(在瀏覽器指的是window對(duì)象),頂層對(duì)象屬性和全局變量是等價(jià)的。屬性也可以動(dòng)態(tài)創(chuàng)建變量,頂層對(duì)象的屬性可以被隨處讀寫不利于模塊化編程;而在ES6中,var命令和function命令聲明的全局變量,依舊是頂層對(duì)象的屬性;另一方面規(guī)定,let命令、const命令、class命令聲明的全局變量,不屬于頂層對(duì)象的屬性。也就是說(shuō),從 ES6 開始,全局變量將逐步與頂層對(duì)象的屬性脫鉤。
var aaa=1;console.log(window.aaa); //輸出1let bbb=2;console.log(window.bbb ); //輸出undefined總結(jié)
以上是生活随笔為你收集整理的详解var、let、const关键词声明变量的区别,以及变量提升、块级作用域的认识等。的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: js数组遍历和对象遍历
- 下一篇: rust(51)-rust工具,prel