前言:
在早期的ES標(biāo)準(zhǔn)中,只有var一種聲明類(lèi)型。經(jīng)過(guò)了好幾年的探索,歐洲電子協(xié)會(huì)終于在2015年發(fā)布了ES6標(biāo)準(zhǔn),新增加了let和const兩個(gè)重要關(guān)鍵字。如今對(duì)于大多數(shù)的互聯(lián)網(wǎng)企業(yè)來(lái)說(shuō),他們也已經(jīng)慢慢采用了ES6規(guī)范。所以,如果你在通篇js中只使用var去聲明甚至不去聲明,那么你的js代碼是非常糟糕且難于理解的。在真正的互聯(lián)網(wǎng)企業(yè)中,你這種行為也是會(huì)被痛批的。(此處應(yīng)有笑臉)所以我們很有必要去深入地了解var、let和const之間的區(qū)別,做到規(guī)范寫(xiě)代碼。
-
首先我們看一下下面這份表:
var let const 初始值 不需要 不需要 需要 重復(fù)聲明 允許 不允許 不允許 變量提升 允許 不允許 不允許 作用域 全局、局部 塊級(jí) 塊級(jí) 暫存死區(qū) 不會(huì) 會(huì) 會(huì)
?。?!敲重點(diǎn),這個(gè)表格大家一定背熟,面試時(shí)基本都會(huì)問(wèn)到。
下面我們結(jié)合代碼來(lái)一個(gè)個(gè)詳細(xì)地介紹它們的區(qū)別,做到知其然,亦知其所以然。
1、初始值
(1)var、let聲明變量可以賦值也可以不賦值:
var initialValue;//initialValue還沒(méi)賦值,合法 var initialValue = 2;//initalValue = 2,合法let initialValue;//initialValue還沒(méi)賦值,合法 let initialValue = 3;//initialValue = 3,合法(2)const聲明變量同時(shí)必須賦值:
const initialValue;//initialValue還沒(méi)賦值,不合法 const initialValue = 4;//initialValue = 4,合法2、重復(fù)聲明
(1)var允許重復(fù)聲明:
<script> var i = 10;//i = 10 var i = 2;//此時(shí)i = 2 var i = 5;//此時(shí)i = 5 if(1) { var i = 100;//此時(shí)i = 100 } console.log(i);//此時(shí)i = 100 </script>注:所以大家發(fā)現(xiàn)了嗎,當(dāng)我使用var聲明一個(gè)變量時(shí),我可以對(duì)同一個(gè)變量進(jìn)行賦值,其變量最終的值為最后聲明的那次。
(2)let、const不允許重復(fù)聲明:
<script> let a = 100;//a = 100,合法 let a = 10;//不合法 const x = 20;//x = 20,合法 const x = 2;//不合法 </script>注:從上面代碼可以看出,當(dāng)我們使用let或者const聲明一個(gè)變量的值時(shí),這個(gè)變量就不能再使用let、const去聲明了,但是并不代表不能再賦值。這是兩個(gè)不一樣的意思,var、let聲明的是可以重新賦值的,而const是不能重新賦值的。
3、變量提升
(1)var允許變量提升:
<script> x = 10; var x; console.log(x);//此時(shí)控制臺(tái)輸出x = 10; </script>注:在JavaScript中,允許var關(guān)鍵字聲明的變量可以先使用后再聲明。
(2)let、const不允許變量提升:
<script> x = 10; let x; console.log(x);//此時(shí)控制臺(tái)輸出undefined y = 10; const y; console.log(y);//報(bào)錯(cuò),因?yàn)閥沒(méi)有賦值 </script>注:從上面代碼可以看出let和const不允許變量先使用后再聲明。但是在日常的編寫(xiě)代碼習(xí)慣中,很少有人會(huì)先使用變量后再聲明,因?yàn)檫@是不符合代碼邏輯的。因此,重在了解,這個(gè)對(duì)我們代碼編寫(xiě)沒(méi)多大用處。
4、作用域
(1)var的作用域包含全局和局部,除了塊級(jí)之外(什么是塊級(jí)作用域下面會(huì)說(shuō)到):
<script> var x = 1;//在函數(shù)外聲明的變量的作用域是全局的 for(let i = 0;i<5;i++){ var x = 100;//在函數(shù)內(nèi)聲明的變量的作用域是局部的 } console.log(x);//可以訪問(wèn),x=100 </script>(2)let、const的作用在塊級(jí)內(nèi):
<script> let x = 1; for(let i=0;i<1;i++){ let x = 5; console.log(x);//x=5 } console.log(x);//x=1 </script>注:從上面代碼可以看出,像{}就叫做塊,使用let聲明的變量互不影響,變量只在其作用域內(nèi)有意義。至于const的也是同理,這里不再贅述。一般我們使用const都是在全局中聲明常量。
5、暫存死區(qū)
(1)var不會(huì)暫存死區(qū):
<script> var a = 10; if(1){ a = 100; var a; } console.log(a);//控制臺(tái)輸出a = 100 </script>(2)let和const會(huì)暫存死區(qū):
<script> let a = 10; if(1){ a = 100; let a; } console.log(a);//報(bào)錯(cuò),找不到a const b = 20; if(1){ b = 200; const b; } console.log(b);//報(bào)錯(cuò),找不到b </script>注:如果代碼塊中存在let或者const命令,那么塊就會(huì)對(duì)這些命令聲明的變量形成一個(gè)封閉作用域,因此在聲明前使用變量就會(huì)出錯(cuò),而var就不會(huì)。但是在代碼編寫(xiě)中也很少會(huì)這樣編寫(xiě),重在了解。
const關(guān)鍵字
前面有提到const在聲明變量時(shí)必須賦值,也就是初始化,且初始化不能再更改。例如:
<script> const a = 1111; a = 100;//報(bào)錯(cuò) </script>但是本質(zhì)上const聲明的變量并不是常量,并不是一定不能改變的,真正的含義是定義了一個(gè)常量引用的一個(gè)值,當(dāng)我們使用const初始化一個(gè)數(shù)組或者對(duì)象時(shí),其實(shí)是可以改變的,例如:
const person ={ id:1, name:'Tang_Xiaokang', age:20, tele:123456789 }; person.id = 4;//此時(shí)對(duì)象person的屬性id已經(jīng)改為4 console.log(person.id);//輸出4 person ={ id:34, name:'tangxiaokang', age:100, tele:987654321 };//此時(shí)會(huì)報(bào)錯(cuò)注:從上面代碼可以看到,對(duì)一個(gè)對(duì)象使用const進(jìn)行初始化時(shí),整個(gè)對(duì)象是不可以重新賦值的,但是我們是可以修改對(duì)象里面的每一個(gè)屬性的。因?yàn)閷?duì)象里面的屬性并沒(méi)有使用const關(guān)鍵字。(重點(diǎn)?。。。?/p>
最后,經(jīng)過(guò)上面的學(xué)習(xí),相信你已經(jīng)充分了解它們之間的區(qū)別。但是,學(xué)習(xí)了理論還不夠,我們更要在日常編寫(xiě)代碼中使用才行。所以,我們應(yīng)該如何正確的使用這些關(guān)鍵字呢?下面我再簡(jiǎn)單講一下它們的使用場(chǎng)景:
const PI = 3.14;
var x = 100;
let y = 20;
for(let i = 0;i<100;i++){
//一些代碼...
}
所以,它們的優(yōu)先級(jí)可以是:const > let > var。用const聲明變量一般表明了其變量是不能再改變了,也就是通常講的常量。對(duì)于var,一般我們可以在塊或函數(shù)外面使用,而在塊級(jí)里面我們一般使用let較多。自從ES6標(biāo)準(zhǔn)提出后,let其實(shí)完全可以取代var,因?yàn)閮烧咦饔貌畈欢啵攸c(diǎn)是let沒(méi)有副作用?。?!