小編給大家分享一下ES6中變量聲明的方式有哪些,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!
創(chuàng)新互聯(lián)長期為上1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為新城企業(yè)提供專業(yè)的網(wǎng)站設(shè)計制作、做網(wǎng)站,新城網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。在ES5中,變量聲明只有var和function以及隱式聲明三種,在ES6中則增加了let、const、import和class四種。
1. let
1.1 塊級作用域
let聲明的變量的作用域是塊級作用域(這個特性有點類似于后臺語言),ES5 并沒有塊級作用域,只有函數(shù)作用域和全局作用域。
{ let a = 'ES6'; var b = 'ES5'; } console.log(b) // ES5 console.log(a) // ReferenceError: a is not defined.
那么let的塊級作用域有什么好處呢?
let非常適合用于 for循環(huán)內(nèi)部的塊級作用域。JS中的for循環(huán)體比較特殊,每次執(zhí)行都是一個全新的獨立的塊作用域,用let聲明的變量傳入到 for循環(huán)體的作用域后,不會發(fā)生改變,不受外界的影響。看一個常見的面試題目:
for (var i = 0; i <10; i++) { setTimeout(function() { // 同步注冊回調(diào)函數(shù)到異步的宏任務(wù)隊列。 console.log(i); // 執(zhí)行此代碼時,同步代碼for循環(huán)已經(jīng)執(zhí)行完成 }, 0); } // 輸出結(jié)果 10 (共10個) // 這里變量為i的for循環(huán)中,i是一個全局變量,在全局范圍內(nèi)都有效,所以每一次循環(huán),新的i值都會覆蓋舊值,導(dǎo)致最后輸出的是最后一輪i的值,即i的最終結(jié)果為10,實際上都是console.log(10)。涉及的知識點:JS的事件循環(huán)機制,setTimeout的機制等
把 var改成 let聲明:
for (let i = 0; i < 10; i++) { setTimeout(function() { console.log(i); //當前的i僅在本輪的循環(huán)中有效,就是說每一次循環(huán),i其實都是一個新產(chǎn)生的變量。 //用 let 聲明的變量 i 只作用于循環(huán)體內(nèi)部,不受外界干擾。 }, 0); } // 輸出結(jié)果: 0 1 2 3 4 5 6 7 8 9
1.2 暫時性死區(qū)(Temporal Dead Zone)
在一個塊級作用域中,變量唯一存在,一旦在塊級作用域中用let聲明了一個變量,那么這個變量就唯一屬于這個塊級作用域,不受外部變量的影響,如下面所示。
var tmp = 'bread and dream'; if(true){ tmp = 'dream or bread'; //ReferenceError let tmp; }
這個例子中tmp = 'dream or bread'的賦值會報錯,因為在if塊中的let對tmp變量進行了聲明,導(dǎo)致該tmp綁定了這個作用域,而let臨時死區(qū)導(dǎo)致了并不能在聲明前使用,所以在聲明前對變量賦值會報錯。
暫時性死區(qū)的本質(zhì)就是,只要一進入當前作用域,所要使用的變量就已經(jīng)存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量。
暫時性死區(qū)的意義也是讓我們標準化代碼,將所有變量的聲明放在作用域的最開始。
1.3 不允許重復(fù)聲明
(1) 在相同的作用域內(nèi),用let聲明變量時,只允許聲明一遍,但 var是可以多次聲明的。大家都知道ES5 多次聲明會造成變量覆蓋而且不會報錯,這就給調(diào)試增加了難度,而let能夠直接扼殺這個問題在搖籃之中,因為會直接報錯。
// 不報錯 function demo() { var a = 'bread and dream'; var a = 'dream or bread'; } // 報錯,Duplicate declaration "a" function demo() { let a = 'bread and dream'; var a = 'dream or bread'; } // 報錯,Duplicate declaration "a" function demo() { let a = 'bread and dream'; let a = 'dream or bread'; }
(2) 不能在函數(shù)內(nèi)部重新聲明參數(shù):
function demo1(arg) { let arg; // 報錯 } demo1() function demo2(arg) { { let arg; // 不報錯 } } demo2()
2. const
2.1 用于聲明常量
const聲明的常量是不允許改變的,只讀屬性,這意味常量聲明時必須同時賦值, 只聲明不賦值,就會報錯,通常常量以大寫字母命名。
const Person; // 錯誤,必須初始化 const Person = 'bread and dream';// 正確 const Person2 = 'no'; Person2 = 'dream or bread'; //報錯,不能重新賦值
這樣做的兩個好處:一是閱讀代碼的人立刻會意識到不應(yīng)該修改這個值,二是防止了無意間修改變量值所導(dǎo)致的錯誤。比如我們使用nodejs的一些模塊的時候,我們只是使用對應(yīng)的模塊(如http模塊),但是并不需要修改nodejs的模塊,這個時候就可以聲明成const,增加了代碼的可讀性和避免錯誤。
2.2 支持塊級作用域
const和let類似,也是支持塊級作用域.
if (true) { const MIN = 5; } MIN // Uncaught ReferenceError: MIN is not defined
2.3 不支持變量提升,有暫時性死區(qū)
const聲明的常量也是不提升,同樣存在暫時性死區(qū),只能在聲明的位置后面使用。
if (true) { console.log(MIN); // ReferenceError const MIN = 5; }
2.4 特殊情況
如果聲明的常量是一個對象,那么對于對象本身是不允許重新賦值的,但是對于對象的屬性是可以賦值的。
const obj = {}; obj.a = 'xiao hua'; console.log(obj.a); //'xiao hua'
實際上const能保證的,并不是變量的值不得改動,而是變量指向的那個內(nèi)存地址所保存的數(shù)據(jù)不得改動。
對于簡單類型的數(shù)據(jù)(數(shù)值、字符串、布爾值),值就保存在變量指向的那個內(nèi)存地址,因此等同于常量。
但對于復(fù)合類型的數(shù)據(jù)(主要是對象和數(shù)組),變量指向的內(nèi)存地址,保存的只是一個指向?qū)嶋H數(shù)據(jù)的指針。
至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。
如果要徹底將對象凍結(jié)(不可修改其屬性),應(yīng)該使用Object.freeze(obj)方法。同理,數(shù)組也是一樣的。
3. import
ES6采用import來代替node等的require來導(dǎo)入模塊。
import {$} from './jquery.js'
$對象就是jquery中export暴露的對象。
如果想為輸入的變量重新取一個名字,import命令要使用as關(guān)鍵字,將輸入的變量重命名。
import { JQ as $ } from './jquery.js';
注意,import命令具有提升效果,會提升到整個模塊的頭部,首先執(zhí)行。
4. class
ES6引入了類的概念,有了class這個關(guān)鍵字。類的實質(zhì)還是函數(shù)對象。
先定義一個類:
//定義類 class Animal { constructor(name, age) { this.name = name; this.age = age; } setSex(_sex) { this.sex=_sex; } }
constructor方法,就是構(gòu)造方法,也就是ES5時代函數(shù)對象的主體,而this關(guān)鍵字則代表實例對象。
上面的類也可以改成ES5的寫法:
function Animal(name, age){ this.name = name; this.age = age; } Animal.prototype.setSex = function (_sex) { this.sex=_sex; }
其實,大多數(shù)類的特性都可以通過之前的函數(shù)對象與原型來推導(dǎo)。
生成類的實例對象的寫法,與ES5通過構(gòu)造函數(shù)生成對象完全一樣,也是使用new命令。
class Animal {} let dog = new Animal();
在類的實例上面調(diào)用方法,其實就是調(diào)用原型上的方法,因為類上的方法其實都是添加在原型上。
Class其實就是一個function,但是有一點不同,Class不存在變量提升,也就是說Class聲明定義必須在使用之前。
5.總結(jié)
在ES6之前,JavaScript是沒有塊級作用域的,如果在塊內(nèi)使用var聲明一個變量,它在代碼塊外面仍舊是可見的。ES6規(guī)范給開發(fā)者帶來了塊級作用域,let和const都添加了塊級作用域,使得JS更嚴謹和規(guī)范。
let 與 const 相同點:
塊級作用域
有暫時性死區(qū)
約束了變量提升
禁止重復(fù)聲明變量
let 與 const不同點:
const聲明的變量不能重新賦值,也是由于這個規(guī)則,const變量聲明時必須初始化,不能留到以后賦值。
合理的使用ES6新的聲明方式,不管是面試還是工作中都有實際的應(yīng)用,尤其是工作中,大家一定要盡量的多使用新的聲明方式,不但可以讓代碼更規(guī)范,更可以避免不必要的bug,浪費調(diào)試時間,進而提高工作效率。
看完了這篇文章,相信你對ES6中變量聲明的方式有哪些有了一定的了解,想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)網(wǎng)站制作公司行業(yè)資訊頻道,感謝各位的閱讀!