ES6 - let车遂、const封断、var的區(qū)別

為了使JavaScript語言可以用來編寫復雜的大型應用程序斯辰,成為企業(yè)級開發(fā)語言舶担,ECMAScript 6.0(簡稱ES6)在標準中添加了很多新的特性。我們將用幾篇文章總結一下ES6標準中一些常用的新特性彬呻。本片文章主要講解ES6中的let衣陶、const命令柄瑰,并區(qū)分其與var命令的區(qū)別。同時歡迎大家隨時指正錯誤剪况、探討交流教沾。

本文已同步至我的個人主頁。歡迎訪問查看更多內容译断!謝謝大家的關注和支持授翻!

let 與 var 的區(qū)別

一、let聲明的變量只在其所在的塊級作用于有效

所謂塊級作用域是指:將多個代碼語句封裝在一起孙咪,通常是包含在一個大括號中堪唐,沒有返回值。比如:

if (true) {  // 塊級作用域  }

for (let i = 0; i < 10; i++) {  // 塊級作用域  }

while (true) {  // 塊級作用域  }

switch (case) {  // 塊級作用域  }

以上例子翎蹈,大括號({...})中形成的都屬于塊級作用域淮菠。

眾所周知,在ES6之前荤堪,JavaScript中只有全局作用域和局部(函數)作用域合陵,不存在塊級作用域。而且也只能使用關鍵字var來聲明變量澄阳。所以用var聲明的變量要么是屬于全局作用域的全局變量拥知,要么就是屬于局部(函數)作用域的局部變量。

在ES6標準中碎赢,添加了使用let聲明變量的方式举庶。使用let聲明的變量只在塊級作用域中有效,在其外層作用域訪問時就會報錯揩抡。

if (true) {
    // 這個用let聲明的變量a户侥,只在當前塊級作用域中有效
    let a = 123;
    // 這個用var聲明的變量b,在全局作用域中都有效
    var b = '123';

    console.log(a);     // 123
    console.log(b);     // '123'
}

console.log(a);     // 報錯 —— ReferenceError: a is not defined.
console.log(b);     // '123'

上面的例子中峦嗤,因為變量a是使用let聲明的蕊唐,它只在其所在的塊級作用域——if后面的大括號({...})之中有效,在塊級作用域外層訪問時就會報錯烁设。而用var聲明的變量b替梨,不受塊級作用域的約束,可以跨塊級作用域訪問装黑。這個例子中副瀑,變量b實際是屬于全局作用域的全局變量。

那么恋谭,為什么ES6中需要引入塊級作用域的概念呢糠睡?為什么要增加使用let來聲明變量的方式呢?

因為疚颊,如果沒有塊級作用域會導致一些不合理的情形出現狈孔。

1信认、 內層變量可能會覆蓋外層變量。

var a = 'Global';

function inner() {
    if (true) {
        console.log(a);     // undefined
        var a = 'inner';
        /**
         * 以上兩行代碼相當于
         * var a;
         * console.log(a);
         * a = 'inner'; 
         * 再次使用var聲明同名變量a均抽,會覆蓋全局變量a
         */
    }
}

inner();

這個例子嫁赏,當在函數inner內部if代碼塊內首先訪問變量a時,卻得到的是undefined油挥。這是因為緊隨其后var聲明的同名變量a會變量提升并覆蓋全局變量a潦蝇。所以打印出a的值為undefined

2深寥、計數的循環(huán)變量會泄露為全局變量

for (var i = 0; i < 10; i++) {
    // 一些循環(huán)操作
}

console.log(i);     // 10

上面的例子护蝶,for循環(huán)中的循環(huán)變量按道理來說應該只屬于for循環(huán)體,循環(huán)結束就不能再訪問翩迈。但實際這樣用var聲明的i持灰,屬于外層作用域中的變量,也就是說i泄露為全局變量负饲。所以當執(zhí)行到console.log(i)時堤魁,因為i經過循環(huán)已經增加到10,所以打印出i的值為10返十。

二妥泉、let聲明的變量不存在變量提升過程

var聲明的變量,會在其作用域中發(fā)生變量提升的過程洞坑。變量會被提升到作用域頂部盲链,JS默認給變量一個undefined值。在使用var聲明一個變量前訪問它迟杂,得到的值永遠是undefined刽沾。

但是,在ES6中使用let聲明的變量排拷,不存在變量提升過程侧漓。也就是說,不能在使用let聲明任何一個變量前訪問它监氢,否則都會報錯布蔗。

console.log(a);     // 報錯——ReferenceError: a is not defined

let a = 'Hello World!';

三浪腐、let聲明的變量存在“暫時性死區(qū)”

只要使用let聲明了一個變量纵揍,那這個變量就“綁定”到了這個作用域(全局/局部/塊級),該變量就不再受外層作用域的影響议街。

ES6明確規(guī)定泽谨,如果區(qū)塊中存在letconst命令,這個區(qū)塊對這些命令聲明的變量從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量隔盛,就會報錯。

總之拾稳,在代碼塊內吮炕,使用let命令聲明變量之前,該變量都是不可用的访得。這在語法上龙亲,稱為“暫時性死區(qū)”(temporal dead zone,簡稱 TDZ)悍抑。

let g = 'Global';

if (true) {
    g = 'Block';    // 報錯——ReferenceError: g is not defined
    let g;
}

上面的例子中鳄炉,if代碼塊最頂部一直到let聲明變量g之前,都是g的“暫時性死區(qū)”搜骡。在該范圍內訪問g都會報錯拂盯。

四、let聲明的變量不允許再次重復聲明

使用var聲明變量记靡,可以多次重復聲明一個同名變量谈竿。最終變量的值為最后一次聲明賦值的結果。

var a = 123;
var a = 'Hello World!';

console.log(a);     // 'Hello World!'

但是摸吠,在同一作用域(全局/局部/塊級)中不允許使用let重復聲明變量空凸。或者說不允許存在與用let聲明的變量同名的變量寸痢。以下代碼都會報錯呀洲!

// 先var,后let
var a = 123;
// ...一些代碼
let a = 'Hello World!';     // 報錯——Uncaught SyntaxError: Identifier 'a' has already been declared

// 先let啼止,后var
let b = 123;
// ...一些代碼
var b = 'Hello World!';     // 報錯——Uncaught SyntaxError: Identifier 'a' has already been declared

// 先let道逗,再let
let c = 123;
// ...一些代碼
let c = 'Hello World!';     // 報錯——Uncaught SyntaxError: Identifier 'a' has already been declared

五、let聲明的全局變量不會作為window對象的一個屬性

使用var聲明的全局變量献烦,會被JS自動添加在全局對象window上憔辫,作為該對象的一個屬性。

var myVar = 'myName';

console.log(window.myVar);      // 'myName'
console.log(window.hasOwnProperty('myVar'));    // true

但是仿荆,使用let聲明的全局變量不會作為window對象的一個屬性贰您。

let yourVar = 'yourName';

console.log(window.yourVar);      // undefined
console.log(window.hasOwnProperty('yourVar'));    // false

這個例子可以看出,let聲明的全局變量yourVar拢操,并沒有被添加到window對象上锦亦,沒有作為window的一個屬性。

let 與const 的區(qū)別

在ES6中令境,上述所有let所具有的特性杠园,對于const來說同樣存在。但constlet舔庶、var的區(qū)別在于const是用來聲明常量的抛蚁。

常量具有以下特點:

一陈醒、常量值不可修改

一個常量,一旦聲明瞧甩,任何時間钉跷、任何地點都不能修改它的值。

const PI = 3.1415926;

console.log(PI);    // 3.1415926

PI = 3; // 報錯——Uncaught TypeError: Assignment to constant variable.

二肚逸、常量在聲明時必須必須立即初始化(賦初始值)

不能只聲明一個常量名爷辙,但不對其進行初始化賦值。否則在聲明常量時就會報錯朦促。

const PI;   // 報錯——Uncaught SyntaxError: Missing initializer in const declaration

PI = 3.1415926;

三膝晾、常量的值不可修改的實質(重要!N衩帷)

實際上血当,常量的值不變,是指常量指向的那個內存地址中所保存的數據不可更改禀忆。對于簡單的數據類型(數值歹颓,字符串、布爾值)油湖,他們本身具體的值就保存在常量所指向的那個內存地址中巍扛,所以不能修改改簡單類型的數據值。

但是乏德,如果一個常量的值是一個引用類型值撤奸,那么常量所指向的內存地址中實際保存的是指向該引用類型值的一個指針(也就是引用類型值在內存中的地址)。所以const只能保證該引用類型地址不變喊括,但該地址中的具體數據是可以變化的胧瓜。

下面的例子,代碼不會報錯郑什,可以正常運行府喳!

// !!!常量OBJ中實際保存的是后面的對象在內存中的地址!!!
const OBJ = {};

/**
 * !!!!!!!!!!
 * 修改OBJ.prop1,實際只是修改了對象的屬性蘑拯,
 * 但并沒有改變該對象在內存中的地址钝满,
 * 所以常量OBJ并沒有發(fā)生變化
 * !!!!!!!!!!
 */
OBJ.prop1 = 123;
OBJ.prop2 = 'Hello World!'

/**
 * !!!!!!!!!!
 * 下面這一行就會報錯,
 * 因為此時OBJ指向了另一個對象,OBJ中保存的地址發(fā)生了變化
 * !!!!!!!!!!
 */
OBJ = {};   // 報錯——Uncaught TypeError: Assignment to constant variable.

下面的例子和上面同理申窘。

const ARR = [];
ARR.push('Hello');  // 可執(zhí)行
ARR.length = 0;     // 可執(zhí)行
ARR = ['Dave'];     // 報錯弯蚜,因為ARR重新指向了數組['Dave']所在的內存地址
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市剃法,隨后出現的幾起案子碎捺,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收厨,死亡現場離奇詭異晋柱,居然都是意外死亡,警方通過查閱死者的電腦和手機诵叁,發(fā)現死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門雁竞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人黎休,你說我怎么就攤上這事浓领∮窨” “怎么了势腮?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長漫仆。 經常有香客問我捎拯,道長,這世上最難降的妖魔是什么盲厌? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任署照,我火速辦了婚禮,結果婚禮上吗浩,老公的妹妹穿的比我還像新娘建芙。我一直安慰自己,他們只是感情好懂扼,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布禁荸。 她就那樣靜靜地躺著,像睡著了一般阀湿。 火紅的嫁衣襯著肌膚如雪赶熟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天陷嘴,我揣著相機與錄音映砖,去河邊找鬼。 笑死灾挨,一個胖子當著我的面吹牛邑退,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼箫章,長吁一口氣:“原來是場噩夢啊……” “哼园爷!你這毒婦竟也來了?” 一聲冷哼從身側響起乓土,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后趣苏,有當地人在樹林里發(fā)現了一具尸體狡相,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年食磕,在試婚紗的時候發(fā)現自己被綠了尽棕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡彬伦,死狀恐怖滔悉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情单绑,我是刑警寧澤回官,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站搂橙,受9級特大地震影響歉提,放射性物質發(fā)生泄漏。R本人自食惡果不足惜区转,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一苔巨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧废离,春花似錦侄泽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至湘捎,卻和暖如春诀豁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窥妇。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工舷胜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人活翩。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓烹骨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親材泄。 傳聞我的和親對象是個殘疾皇子沮焕,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容