摘要:眾所周知,中的聲明存在變量提升機(jī)制,因此引用了塊級(jí)作用域來強(qiáng)化對(duì)變量生命周期的控制聲明不會(huì)被提升,有幾個(gè)需要注意的點(diǎn)不能被重復(fù)聲明假設(shè)作用域中已經(jīng)存在某個(gè)標(biāo)識(shí)符無論該標(biāo)識(shí)符是通過聲明還是變量聲明,此時(shí)再使用或關(guān)鍵定聲明會(huì)拋錯(cuò)此處則會(huì)拋出錯(cuò)誤
眾所周知,js中的var聲明存在變量提升機(jī)制,因此ESMAScript 6引用了塊級(jí)作用域來強(qiáng)化對(duì)變量生命周期的控制
let const 聲明不會(huì)被提升,有幾個(gè)需要注意的點(diǎn)
1、不能被重復(fù)聲明
假設(shè)作用域中已經(jīng)存在某個(gè)標(biāo)識(shí)符(無論該標(biāo)識(shí)符是通過var聲明還是let、const變量聲明),此時(shí)再使用let或const關(guān)鍵定聲明會(huì)拋錯(cuò)
var count=10 let count=20// 此處則會(huì)拋出錯(cuò)誤,因?yàn)橥蛔饔糜騼?nèi)不能重復(fù)聲明
如果當(dāng)前作用域內(nèi)嵌另一個(gè)作用域,便可在內(nèi)嵌的作用域中用let聲明同名變量
var count=10 if(true){ let count=20 }
2、const聲明的常量必須進(jìn)行初始化
像下面這樣聲明就會(huì)報(bào)錯(cuò)
const name;//語法錯(cuò)誤,常量未初始化
3、不可以為const定義的常量再賦值,真正的本質(zhì)是const聲明不允許修改綁定,但允許修改值(也就是說const聲明對(duì)象后,可以修改該對(duì)象的屬性值)
const person={ name:"angela" } //可以修改對(duì)象屬性的值 person.name="yun" // 修改綁定則會(huì)拋出語法錯(cuò)誤 person={ "name":"Shining" }
4、臨時(shí)性死區(qū)(Temporal Dead Zone)
JavaScript引擎在掃描代碼發(fā)現(xiàn)變量聲明時(shí),要么將它們提升至作用域頂部(遇到var聲明),要么將聲明放到TDZ中(遇到let和const聲明),訪問TDZ中的變量會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤,只有執(zhí)行過變量聲明語句后,變量才會(huì)從TDZ中移出,才能正常訪問
如下代碼就因?yàn)樵趇f塊級(jí)作用域內(nèi)執(zhí)行console.log時(shí)value已經(jīng)在TDZ中了,以前typeof是一個(gè)相對(duì)不易出錯(cuò)的操作符,但其實(shí)也無法阻擋引擎拋出錯(cuò)誤
在聲明前訪問塊級(jí)綁定會(huì)導(dǎo)致錯(cuò)誤,因?yàn)榻壎ㄔ谂R時(shí)死區(qū)中
if (true) { console.log(typeof value)//引用錯(cuò)誤 let value = "blue" }
而在let聲明的作用域外對(duì)該變量使用typeof則不會(huì)報(bào)錯(cuò)
console.log(typeof value) if (true) { let value = "blue" }
5、塊級(jí)作用域綁定
之前在循環(huán)中創(chuàng)建函數(shù)都有些不可言狀
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func() })
因?yàn)檠h(huán)內(nèi)部創(chuàng)建的函數(shù)全部都保留了對(duì)相同變量的引用,循環(huán)結(jié)束時(shí)變量i的值為10,所以結(jié)果會(huì)輸出10次10
于是大家會(huì)在循環(huán)中使用立即調(diào)用函數(shù)表達(dá)式,以強(qiáng)制生成計(jì)數(shù)器變量的副本,以便輸出1、2、3......
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function (value) { return function () { console.log(value) } })(i)) } funcs.forEach(function (func) { func() })
有了let,立即調(diào)用函數(shù)表達(dá)式則可以簡化,其實(shí)每次迭代循環(huán)都會(huì)創(chuàng)建一個(gè)新變量,并以之前迭代中同名變量的值將其初始化
var funcs = [] for (let i = 0; i < 10; i++) { //其實(shí)是每次循環(huán)的時(shí)候let聲明都會(huì)創(chuàng)建一個(gè)新變量i并將其初始化為i的當(dāng)前值,所以在循環(huán)內(nèi)部創(chuàng)建的每個(gè)函數(shù)都能得到屬于它們自己的i的副本 funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func()//這里輸出是0 然后是1、2....9 })
這個(gè)特性同樣適用于for in中,舉例來說
var funcs = [], obj = { a: true, b: true, c: true } for (let key in obj) { funcs.push(function () { console.log(key) }) } funcs.forEach(function (func) { func()//輸出的是a b c })
6、循環(huán)中的let聲明特性同樣適用于const聲明,唯一的區(qū)別是const不能更改綁定
上面的例子中把let換成const同樣輸出a b c
var funcs = [], obj = { a: true, b: true, c: true } //之所以可以運(yùn)用for in 和for of循環(huán)中,是因?yàn)槊看蔚粫?huì)修改已有綁定,而是會(huì)創(chuàng)建一個(gè)新綁定 for (const key in obj) { funcs.push(function () { console.log(key)// 同樣輸出a b c 唯一的區(qū)別是循環(huán)內(nèi)不能更改key的值 }) } funcs.forEach(function (func) { func() })
下面的這個(gè)例子則會(huì)報(bào)錯(cuò),因?yàn)樵趂or循環(huán)中更改了i的綁定而const常量不能更改綁定
var funcs = [] for (const i = 0; i < 10; i++) { funcs.push(function () { console.log(i) }) } funcs.forEach(function (func) { func() })
7、全局作用域綁定
當(dāng)var被作用于全局作用域時(shí),它會(huì)創(chuàng)建一個(gè)新的全局變量作用全局對(duì)象(瀏覽器環(huán)境中的window對(duì)象)的屬性,這意味著用var很可能會(huì)無意中覆蓋一個(gè)已經(jīng)存在的全局變量
從上圖代碼中看出即便是全局對(duì)象RegExp Array都會(huì)被覆蓋
但是let或const會(huì)在全局作用域下創(chuàng)建一個(gè)新的綁定,但該綁定不會(huì)添加為全局對(duì)象的屬性,換句話說用let或const不能覆蓋全局變量,而只能遮蔽它
這個(gè)時(shí)候的RegExp和window.RegExp是不相同的
let RegExp="hello" console.log(RegExp) //hello console.log(window.RegExp===RegExp)//false const ncz="hi" console.log(ncz) console.log("ncz" in window)
最佳實(shí)踐:
默認(rèn)使用let而不是var
默認(rèn)使用const,只有確實(shí)需要改變變量的值時(shí)使用let
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/87372.html
摘要:沒有聲明的情況和都能夠聲明塊級(jí)作用域,用法和是類似的,的特點(diǎn)是不會(huì)變量提升,而是被鎖在當(dāng)前塊中。聲明常量,一旦聲明,不可更改,而且常量必須初始化賦值。臨時(shí)死區(qū)的意思是在當(dāng)前作用域的塊內(nèi),在聲明變量前的區(qū)域叫做臨時(shí)死區(qū)。 本章涉及3個(gè)知識(shí)點(diǎn),var、let、const,現(xiàn)在讓我們了解3個(gè)關(guān)鍵字的特性和使用方法。 var JavaScript中,我們通常說的作用域是函數(shù)作用域,使用var聲...
摘要:閉包面試題解由于作用域鏈機(jī)制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個(gè)值,這引起的一個(gè)副作用就是如果內(nèi)部函數(shù)在一個(gè)循環(huán)中,那么變量的值始終為最后一個(gè)值。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第8天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了...
摘要:塊級(jí)聲明前是沒有塊級(jí)作用域的,比如外可以訪問內(nèi)部的變量。循環(huán)中的塊作用域綁定我們經(jīng)常使用循環(huán)發(fā)現(xiàn)了什么在循環(huán)執(zhí)行后,我們?nèi)匀豢梢栽L問到變量。 var聲明及變量提升機(jī)制 在ES6之前,在函數(shù)作用域中或者全局作用域中通過var關(guān)鍵字來聲明變量,無論是在代碼的哪個(gè)位置,這條聲明語句都會(huì)提到最頂部來執(zhí)行,這就是變量聲明提升。 注意:只是聲明提升,初始化并沒有提升。 看一個(gè)例子: functio...
閱讀 3062·2021-11-15 18:02
閱讀 3961·2021-10-14 09:43
閱讀 3962·2021-09-08 10:41
閱讀 2658·2019-08-30 15:53
閱讀 1939·2019-08-30 14:14
閱讀 2094·2019-08-29 16:12
閱讀 3286·2019-08-29 14:03
閱讀 1415·2019-08-29 13:46