ES6標準入門之 let與const

var用的好好的挪鹏,為甚es6要出let和const去替換var呢袁辈?

當然是為自己曾經(jīng)犯下的錯誤買單!

在講解es6之前挖滤,我們必須要提一下es5中的var,也就是曾經(jīng)的那個錯誤浅役。

if (condition) {

? ? var value = 1;

}

console.log(value);

很簡單的分析一下斩松,初學者可能會認為,只有在condition為true的時候担租,value才會被賦值砸民,如果condition為false的時候,代碼應該會報錯才對奋救!但是岭参,事實并不是這樣的,瀏覽器在執(zhí)行這段代碼的時候尝艘,并不是這么解析的演侯!

var value;

if (condition) {

? ? value = 1;

}

console.log(value);

這樣,很容易我們就能判斷出背亥,如果condition的值為false的時候秒际,console出來的值為undefined悬赏。

原因就是我們常說的,變量提升娄徊。

為了加強對變量生命周期的控制闽颇,ECMAScript 6 引入了塊級作用域。

塊級作用域存在于:

? ? ? ?1.函數(shù)內(nèi)部

? ? ? ? 2.塊中(字符 { 和 } 之間的區(qū)域)

引出我們今天的主角—let和const

let 和 const 都是塊級聲明的一種寄锐。

let和const的特點:

1.不會被提升(真的是這樣的嗎兵多?)

if ( condition ) {

? ? let value = 1;

}

console.log(value); // Uncaught ReferenceError: value is not defined?


在代碼塊外面訪問,直接判定橄仆,為定義剩膘。

2.重復聲明報錯

var value = 1;

let value = 2; // Uncaught SyntaxError: Identifier 'value' has already been declared

這在以前是完全可以的,后定義的回覆蓋以前的盆顾。

3.不綁定全局作用域

let value = 1 ;

console.log(window.value);

const也是相同的怠褐,都訪問不到。

const和let的區(qū)別:

const 用于聲明常量您宪,其值一旦被設(shè)定不能再被修改奈懒,否則會報錯。

值得一提的是:const 聲明不允許修改綁定蚕涤,但允許修改值筐赔。這意味著當用 const 聲明對象時:

const data = {

? ? value: 1

}

// 沒有問題

data.value = 2;

data.num = 3;

// 報錯

data = {}; // Uncaught TypeError: Assignment to constant variable.

臨時死區(qū)

臨時死區(qū)(Temporal Dead Zone),簡寫為 TDZ揖铜。

let 和 const 聲明的變量不會被提升到作用域頂部,如果在聲明之前訪問這些變量达皿,會導致報錯天吓。

console.log(typeof value); // Uncaught ReferenceError: value is not defined

let value = 1;

來個例子?

var value = "global";

// 例子1

(function() {

? ? console.log(value);

? ? let value = 'local';

}());

// 例子2

{

? ? console.log(value);

? ? const value = 'local';

};


結(jié)果是:都報錯了B鸵A淠!

這是因為 JavaScript 引擎在掃描代碼發(fā)現(xiàn)變量聲明時汤功,要么將它們提升到作用域頂部(遇到 var 聲明)物邑,要么將聲明放在 TDZ 中(遇到 let 和 const 聲明)。訪問 TDZ 中的變量會觸發(fā)運行時錯誤滔金。只有執(zhí)行過變量聲明語句后色解,變量才會從 TDZ 中移出,然后方可訪問餐茵。

循環(huán)中的塊級作用域

var funcs = [];

for (var i = 0; i < 3; i++) {

? ? funcs[i] = function () {

? ? ? ? console.log(i);

? ? };

}

funcs[0](); // 3

如何改變現(xiàn)狀呢科阎?我要的是funcs[0]() == 0

在沒有es6 之前,這個事兒麻煩了忿族,還得使用閉包的方式锣笨!

var funcs = [];

for (var i = 0; i < 3; i++) {

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

? ? ? ? return function() {

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

? ? ? ? }

? ? }(i))

}

funcs[0](); // 0

ES6 的 let 為這個問題提供了新的解決方法:

var funcs = [];

for (let i = 0; i < 3; i++) {

? ? funcs[i] = function () {

? ? ? ? console.log(i);

? ? };

}

funcs[0](); // 0


問題在于蝌矛,上面講了 let 不提升,不能重復聲明错英,不能綁定全局作用域等等特性入撒,可是為什么在這里就能正確打印出 i 值呢?

如果是不重復聲明椭岩,在循環(huán)第二次的時候衅金,又用 let 聲明了 i,應該報錯呀簿煌,就算因為某種原因氮唯,重復聲明不報錯,一遍一遍迭代姨伟,i 的值最終還是應該是 3 呀惩琉,還有人說 for 循環(huán)的 設(shè)置循環(huán)變量的那部分是一個單獨的作用域,就比如:

for (let i = 0; i < 3; i++) {

? let i = 'abc';

? console.log(i);

}

// abc

// abc

// abc

這個例子是對的夺荒,如果我們把 let 改成 var 呢瞒渠?

for (var i = 0; i < 3; i++) {

? var i = 'abc';

? console.log(i);

}

// abc

經(jīng)查, for 循環(huán)中使用 let 和 var技扼,底層會使用不同的處理方式伍玖。

簡單的來說,就是在?for (let i = 0; i < 3; i++)?中剿吻,即圓括號之內(nèi)建立一個隱藏的作用域窍箍,這就可以解釋為什么:

for (let i = 0; i < 3; i++) {

? let i = 'abc';

? console.log(i);

}

// abc

// abc

// abc

然后每次迭代循環(huán)時都創(chuàng)建一個新變量,并以之前迭代中同名變量的值將其初始化丽旅。

var funcs = [];

for (let i = 0; i < 3; i++) {

? ? funcs[i] = function () {

? ? ? ? console.log(i);

? ? };

}

funcs[0](); // 0

相當于:

// 偽代碼

(let i = 0) {

? ? funcs[0] = function() {

? ? ? ? console.log(i)

? ? };

}

(let i = 1) {

? ? funcs[1] = function() {

? ? ? ? console.log(i)

? ? };

}

(let i = 2) {

? ? funcs[2] = function() {

? ? ? ? console.log(i)

? ? };

};

到此椰棘,我們就講完了嗎?沒有榄笙,并沒有邪狞,上面還有個提升的問題么!

首先明確一點:提升不是一個技術(shù)名詞茅撞。

要搞清楚提升的本質(zhì)帆卓,需要理解 JS 變量的「創(chuàng)建create、初始化initialize 和賦值assign」

假設(shè)有如下代碼:

function fn(){

? var x = 1

? var y = 2

}

fn()

在執(zhí)行 fn 時米丘,會有以下過程(不完全):

進入 fn剑令,為 fn 創(chuàng)建一個環(huán)境。

找到 fn 中所有用 var 聲明的變量蠕蚜,在這個環(huán)境中「創(chuàng)建」這些變量(即 x 和 y)尚洽。

將這些變量「初始化」為 undefined。

開始執(zhí)行代碼

x = 1 將 x 變量「賦值」為 1

y = 2 將 y 變量「賦值」為 2

也就是說 var 聲明會在代碼執(zhí)行之前就將「創(chuàng)建變量靶累,并將其初始化為 undefined」腺毫。

這就解釋了為什么在 var x = 1 之前 console.log(x) 會得到 undefined癣疟。

接下來來看 function 聲明的「創(chuàng)建、初始化和賦值」過程

假設(shè)代碼如下:

fn2()

function fn2(){

? console.log(2)

}

JS 引擎會有一下過程:

找到所有用 function 聲明的變量潮酒,在環(huán)境中「創(chuàng)建」這些變量睛挚。

將這些變量「初始化」并「賦值」為 function(){ console.log(2) }。

開始執(zhí)行代碼 fn2()

也就是說 function 聲明會在代碼執(zhí)行之前就「創(chuàng)建急黎、初始化并賦值」扎狱。

接下來看 let 聲明的「創(chuàng)建、初始化和賦值」過程

假設(shè)代碼如下:

{

? let x = 1

? x = 2

}


我們只看 {} 里面的過程:

找到所有用 let 聲明的變量勃教,在環(huán)境中「創(chuàng)建」這些變量

開始執(zhí)行代碼(注意現(xiàn)在還沒有初始化)

執(zhí)行 x = 1淤击,將 x 「初始化」為 1(這并不是一次賦值,如果代碼是 let x故源,就將 x 初始化為 undefined)

執(zhí)行 x = 2污抬,對 x 進行「賦值」

這就解釋了為什么在 let x 之前使用 x 會報錯:

let x = 'global'

{

? console.log(x) // Uncaught ReferenceError: x is not defined?

? let x = 1

}


原因有兩個:

1.console.log(x) 中的 x 指的是下面的 x,而不是全局的 x

2.執(zhí)行 log 時 x 還沒「初始化」绳军,所以不能使用(也就是所謂的暫時死區(qū))

看到這里印机,你應該明白了 let 到底有沒有提升:

let 的「創(chuàng)建」過程被提升了,但是初始化沒有提升门驾。

var 的「創(chuàng)建」和「初始化」都被提升了射赛。

function 的「創(chuàng)建」「初始化」和「賦值」都被提升了。

最后看 const奶是,其實 const 和 let 只有一個區(qū)別楣责,那就是 const 只有「創(chuàng)建」和「初始化」,沒有「賦值」過程诫隅。

這四種聲明腐魂,用下圖就可以快速理解:

所謂暫時死區(qū),就是不能在初始化之前逐纬,使用變量。

至此削樊,我們結(jié)束今天的分享...

引用:https://juejin.im/post/5b0238f66fb9a07aca7a74ba

? ? ? ? ? ?https://zhuanlan.zhihu.com/p/28140450

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末豁生,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子漫贞,更是在濱河造成了極大的恐慌甸箱,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迅脐,死亡現(xiàn)場離奇詭異芍殖,居然都是意外死亡,警方通過查閱死者的電腦和手機谴蔑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門豌骏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龟梦,“玉大人,你說我怎么就攤上這事窃躲〖品。” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵蒂窒,是天一觀的道長躁倒。 經(jīng)常有香客問我,道長洒琢,這世上最難降的妖魔是什么秧秉? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮衰抑,結(jié)果婚禮上象迎,老公的妹妹穿的比我還像新娘。我一直安慰自己停士,他們只是感情好挖帘,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恋技,像睡著了一般拇舀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜻底,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天骄崩,我揣著相機與錄音,去河邊找鬼薄辅。 笑死要拂,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的站楚。 我是一名探鬼主播脱惰,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼窿春!你這毒婦竟也來了拉一?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旧乞,失蹤者是張志新(化名)和其女友劉穎蔚润,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尺栖,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡嫡纠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片除盏。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡叉橱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痴颊,到底是詐尸還是另有隱情赏迟,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布蠢棱,位于F島的核電站锌杀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏泻仙。R本人自食惡果不足惜糕再,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玉转。 院中可真熱鬧突想,春花似錦、人聲如沸究抓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刺下。三九已至绑嘹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橘茉,已是汗流浹背工腋。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留畅卓,地道東北人擅腰。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像翁潘,于是被迫代替她去往敵國和親趁冈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

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