JavaScript塊級作用域綁定以及狀態(tài)提升詳解
前言
在ES6之前,JavaScript只有經(jīng)典的var聲明,這給開發(fā)者帶來了很多的困擾。在ES6出現(xiàn)后,又增加了let和const關(guān)鍵字的聲明方式。這里會講有關(guān)變量聲明,作用域,狀態(tài)提升相關(guān)知識。
作用域/執(zhí)行上下文
在JavaScript的世界里,作用域可以分為三種,分別是全局作用域,函數(shù)作用域,塊級作用域。
- 全局作用域/執(zhí)行上下文:默認(rèn)或者是最基礎(chǔ)的作用域。一個程序只有一個全局作用域,在JavaScript腳本存在的生命周期中都在執(zhí)行堆棧的底部不會被彈出銷毀。全局作用域中有一個全局對象(以瀏覽器環(huán)境為例,這個全局對象是window)。
- 函數(shù)作用域:一個函數(shù)體內(nèi)部是一個作用域。
- 塊級作用域:存在于塊中——字符 { 和 } 之間的區(qū)域。(顯然函數(shù)體也是由大括號包裹的,所以函數(shù)作用域也是塊級作用域)
var 聲明
var聲明在全局作用域中,會被添加到全局對象上成為全局對象的屬性。在函數(shù)作用域中則會被提升到函數(shù)頂部。而且不管實(shí)際是否會執(zhí)行,都會在預(yù)編譯階段將函數(shù)聲明提升,初始化操作則留在本地。
- var聲明的變量會被提升到當(dāng)前作用域頂部(當(dāng)前作用域只包括全局作用域或函數(shù)作用域,沒有塊級作用域)。
塊級聲明
臨時死區(qū)(Temporal Dead Zone,TDZ):用來描述 let 和 const 的不提升效果的術(shù)語。JavaScript引擎在掃描代碼發(fā)現(xiàn)變量聲明時,要么將他們提升到作用域頂部(var聲明),要么將聲明放到TDZ(let聲明和const聲明)。訪問在TDZ中的變量會觸發(fā)運(yùn)行時錯誤,只有執(zhí)行過變量聲明語句后,變量才會從TDZ中移出,然后才可以正常訪問。
const 和 let 是塊級標(biāo)識符,所以聲明的變量、常量也只在當(dāng)前代碼塊中有效,一旦執(zhí)行到塊外就會立即被銷毀。
- let聲明:可以將變量作用域限制在當(dāng)前代碼塊中。在聲明語句前會將變量放在臨時死區(qū)。
- const聲明:用來聲明常量,并且每個被被const聲明的常量必須進(jìn)行初始化。如果是對象,則對象中的值可以修改(cosnt聲明不允許修改綁定,但可以修改綁定的值)
不聲明的變量
在JavaScript中,定義一個變量不使用關(guān)鍵字聲明也不會報(bào)錯。但不建議這么做。
不管在全局,函數(shù)還是塊作用域里,a = 0 這樣的語句都會在 window 對象上創(chuàng)建 a 屬性,實(shí)際上也就是執(zhí)行了 window.a = 0 。而只有在全局作用域中,var a = 0才會在 window 上創(chuàng)建屬性 a,即為 window.a = 0。
1. 不使用關(guān)鍵字聲明變量
function func() { b = 0 console.log(b); console.log(b === window.b); } func() console.log(b === window.b); // 輸出結(jié)果 /* 0 true true */
???? 這部分代碼執(zhí)行過 func 函數(shù),將變量 b 作為 window 對象的屬性。
2. 使用 var 聲明的變量
function func(x) { var b = 0 console.log(b); console.log(b === window.b); } func(1) console.log(b === window.b); // 輸出結(jié)果 /* 0 false Uncaught ReferenceError: b is not defined */
???? 這段代碼就是正常的 var 聲明的變量在函數(shù)作用域內(nèi)提升。
var 聲明和塊級聲明的區(qū)別
全局作用域綁定
- var聲明在全局作用域中時,會創(chuàng)建一個新的全局變量作為全局對象的屬性(在瀏覽器中為window對象)。這意味著用 var 可能會無意中覆蓋一個已經(jīng)存在的全局變量。
- 塊級聲明(let 或 const)會在全局作用域創(chuàng)建一個新的綁定,但該綁定不會添加為全局對象的屬性。所以用塊級聲明不會覆蓋全局變量,只能遮蔽它。
let RegExp = 'Hello!' console.log(RegExp); console.log(window.RegExp === RegExp); // 結(jié)果 /* Hello! false */ 復(fù)制代碼
狀態(tài)提升
- var 聲明的變量會提升到當(dāng)前作用域頂部,在實(shí)例化之前為 undefined。var聲明的變量限制范圍為全局作用域或函數(shù)作用域。
- 塊級聲明的變量會被存放到臨時死區(qū),在實(shí)例化前訪問會報(bào)錯 Uncaught ReferenceError
console.log(RegExp); let RegExp = 'Hello!' // Uncaught ReferenceError: Cannot access 'RegExp' before initialization
塊級綁定的最佳實(shí)踐
默認(rèn)使用 const,只有確實(shí)需要改變變量的值時使用 let。
函數(shù)聲明提升
函數(shù)提升優(yōu)先級高于變量提升。
函數(shù)聲明的特點(diǎn):函數(shù)聲明會被提升到當(dāng)前作用域頂部,并且可以在當(dāng)前作用域內(nèi)部任何地方都可以訪問到。
總結(jié)
到此這篇關(guān)于JavaScript塊級作用域綁定以及狀態(tài)提升的文章就介紹到這了,更多相關(guān)JS塊級作用域綁定/狀態(tài)提升內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript Array.prototype.slice使用說明
slice 可以用來獲取數(shù)組片段,它返回新數(shù)組,不會修改原數(shù)組。2010-10-10修改js confirm alert 提示框文字的簡單實(shí)例
下面小編就為大家?guī)硪黄薷膉s confirm alert 提示框文字的簡單實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06postman自定義函數(shù)實(shí)現(xiàn) 時間函數(shù)的思路詳解
Postman是一款功能強(qiáng)大的網(wǎng)頁調(diào)試與發(fā)送網(wǎng)頁HTTP請求的Chrome插件。這篇文章主要給大家介紹postman自定義函數(shù)實(shí)現(xiàn) 時間函數(shù)的思路詳解,感興趣的朋友一起看看吧2019-04-04js鼠標(biāo)點(diǎn)擊圖片實(shí)現(xiàn)隨機(jī)變換圖片的方法
這篇文章主要介紹了js鼠標(biāo)點(diǎn)擊圖片實(shí)現(xiàn)隨機(jī)變換圖片的方法,涉及鼠標(biāo)事件與隨機(jī)函數(shù)的使用技巧,需要的朋友可以參考下2015-02-02