亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript中Hoisting詳解 (變量提升與函數(shù)聲明提升)

 更新時(shí)間:2017年08月18日 09:36:59   投稿:daisy  
函數(shù)聲明和變量聲明總是被JavaScript解釋器隱式地提升(hoist)到包含他們的作用域的最頂端。下面這篇文章主要給大家介紹了關(guān)于JavaScript中Hoisting(變量提升與函數(shù)聲明提升)的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。

本文主要給大家介紹了關(guān)于JavaScript中Hoisting(變量提升與函數(shù)聲明提升)的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。

如何將 函數(shù)聲明 / 變量 “移動(dòng)” 到作用域的頂部。

術(shù)語(yǔ) Hoisting(提升) 在很多 JavaScript 博文中被用來(lái)解釋標(biāo)識(shí)符的解析。其實(shí) Hoisting(提升) 這個(gè)詞是用來(lái)解釋 變量 和 函數(shù)聲明 是如何被提升到 函數(shù)或全局 作用域頂部的。你在任何的 JavaScript 文檔中找不到這個(gè)術(shù)語(yǔ),我們說(shuō)的 Hoisting(提升) 只是使用了其字面含義來(lái)做個(gè)比喻。

如果你已經(jīng)對(duì) JavaScript 作用域工作原理有基本的了解,那么更深入的了解 Hoisting(提升) 有助于你建立更強(qiáng)大的基礎(chǔ)知識(shí)。(愚人碼頭注:作為 JavaScript 中的一個(gè)總要概念,變量提升和函數(shù)聲明提升經(jīng)常在前端開(kāi)發(fā)面試時(shí)被問(wèn)及,或者在前端開(kāi)發(fā)筆試題中出現(xiàn)。可見(jiàn)了解 Hoisting(提升) 的重要性。)

為了更好地理解基礎(chǔ)知識(shí),讓我們來(lái)回顧一下 “Hoisting(提升)” 到底意味著什么。另外,給你一個(gè)提醒,JavaScript 是一種解釋性語(yǔ)言,這不同于編譯性語(yǔ)言,這意味著JS代碼是逐行執(zhí)行的。

請(qǐng)考慮以下示例:

console.log(notyetdeclared);
// 打印 'undefined'
 
var notyetdeclared = 'now it is declared';
 
hoisting();
 
function hoisting(){
 console.log(notyetdeclared);
 // 打印 'undefined'
 
 var notyetdeclared = 'declared differently';
 
 console.log(notyetdeclared);
 // 打印 'declared differently'
}

在分析上面的示例代碼之后,提出幾個(gè)問(wèn)題:

  • 第 6 行,該函數(shù)聲明之前為何能訪問(wèn)?
  • 第 1 行,沒(méi)有拋出錯(cuò)誤,是因?yàn)檫@時(shí)變量 notyetdeclared 不存在嗎?
  • 第 4 行,notyetdeclared 已經(jīng)在全局作用域內(nèi)聲明了,為什么在第 9 行打印時(shí)還是  undefined 呢?

JavaScript 是非常合乎邏輯的,所有這些奇怪問(wèn)題都有一個(gè)明確的解釋。

我們從頂部開(kāi)始解釋,當(dāng)代碼在 JavaScript 中執(zhí)行時(shí),就會(huì)建立一個(gè)執(zhí)行期上下文。 JavaScript 中有兩種主要的執(zhí)行期上下文類型 – 全局執(zhí)行期上下文和函數(shù)執(zhí)行期上下文(愚人碼頭注:特別注意,執(zhí)行期上下文和我們平常說(shuō)的上下文不同,執(zhí)行期上下文指的是作用域,而平常說(shuō)的上下文是 this 的取值指向)。由于 JavaScript 是基于單線程執(zhí)行模型,所以每次只能執(zhí)行一段代碼。

對(duì)于我們上面的代碼,這個(gè)過(guò)程如圖所示:

上述示例代碼的調(diào)用棧:

  • 程序從棧(stack)上的全局執(zhí)行期上下文開(kāi)始執(zhí)行。
  • 當(dāng)調(diào)用 hoisting() 函數(shù)時(shí),將一個(gè)新的函數(shù)執(zhí)行期上下文推到棧(stack)上,并且全局執(zhí)行期上下文被暫停。
  • 在 hoisting() 執(zhí)行完成后 , hoisting()執(zhí)行期上下文從棧(stack)中彈出,全局執(zhí)行期上下文恢復(fù)。

這個(gè)過(guò)程是自解釋的,但并沒(méi)有真正解釋我們?cè)趫?zhí)行示例代碼時(shí)所看到的異常。當(dāng)執(zhí)行期上下文跟蹤代碼的執(zhí)行情況時(shí),詞法環(huán)境跟蹤標(biāo)識(shí)符到特定變量的映射。詞法環(huán)境基本上是 JavaScript 作用域機(jī)制的內(nèi)部實(shí)現(xiàn)。通常,詞法環(huán)境與 JavaScript 代碼的特定結(jié)構(gòu)相關(guān)聯(lián),例如一個(gè)函數(shù)或一個(gè) for 循環(huán)代碼塊。每當(dāng)創(chuàng)建一個(gè)函數(shù)時(shí),對(duì)其創(chuàng)建的詞法環(huán)境的引用將在一個(gè)名為 [[Environment]] 的內(nèi)部屬性中傳遞。

所有這些術(shù)語(yǔ)涵蓋的是一個(gè)簡(jiǎn)單而非常合乎邏輯的概念。允許將其分解。詞法環(huán)境是一個(gè)有趣的名稱,用于跟蹤代碼塊中的變量和函數(shù)。除了跟蹤局部變量、函數(shù)聲明和參數(shù)之外,每個(gè)詞法環(huán)境還跟蹤其父級(jí)詞法環(huán)境。所以上面的示例代碼在 JavaScript 引擎中會(huì)被這樣解析。上述代碼的詞法環(huán)境,如圖所示:

注:

如果理解起來(lái)有問(wèn)題,請(qǐng)查看以下三篇文章:

為了在詞法環(huán)境中解析標(biāo)識(shí)符, JavaScript 引擎將檢查當(dāng)前環(huán)境的引用。如果沒(méi)有找到引用,則通過(guò)使用 [[environment]] 移動(dòng)到外部環(huán)境。這將一直持續(xù)進(jìn)行下去,直到標(biāo)識(shí)符被找到,或者拋出一個(gè) ‘not defined'(未定義) 的錯(cuò)誤。

基本上,JavaScript 代碼的執(zhí)行分為兩個(gè)階段。第一個(gè)階段在當(dāng)前詞法環(huán)境中注冊(cè)所有的變量和函數(shù)聲明。完成之后,第二個(gè)階段的 JavaScript 執(zhí)行就開(kāi)始了!

所以要詳細(xì)說(shuō)明第一階段:它在兩個(gè)步驟中起作用。

  • 掃描當(dāng)前函數(shù)聲明中的代碼。函數(shù)表達(dá)式和箭頭函數(shù)會(huì)被跳過(guò)。對(duì)于每個(gè)被發(fā)現(xiàn)的函數(shù),都會(huì)創(chuàng)建一個(gè)新的函數(shù),并使用函數(shù)名稱將其綁定到環(huán)境中。如果標(biāo)識(shí)符的名稱已經(jīng)存在,那么它的值就會(huì)被覆蓋。
  • 然后掃描當(dāng)前環(huán)境的變量。找到使用 var 定義的變量和放置在其他函數(shù)之外的變量,并注冊(cè)一個(gè)標(biāo)識(shí)符,其值初始化為 undefined 。如果存在標(biāo)識(shí)符,則該值將保持不變。

注意:用 let 和 const 定義的是塊變量,與 var 的處理稍微不同。在另一篇文章中了解更多的內(nèi)容。

現(xiàn)在你應(yīng)該已經(jīng)對(duì)詞法環(huán)境這個(gè)基本概念有了一定的了解,那么讓我們回到示例代碼中,并解釋這些問(wèn)題。

在設(shè)置全局上下文時(shí),將對(duì)環(huán)境進(jìn)行掃描,并將 hoisting() 函數(shù)附加到標(biāo)識(shí)符上。然后在下一步中,變量 notyetdeclared 被注冊(cè),其值初始化為 undefined 。按照這個(gè)步驟繼續(xù)理解代碼。

現(xiàn)在我們來(lái)解釋示例代碼中提出的3個(gè)問(wèn)題:

第 6 行,該函數(shù)聲明之前為何能訪問(wèn)?

第1階段, hoisting() 函數(shù)已經(jīng)注冊(cè)到了標(biāo)識(shí)符中,當(dāng)JS代碼在第2階段的全局執(zhí)行期上下文中開(kāi)始執(zhí)行時(shí),它會(huì)查找 hoisting 的詞法環(huán)境,并在其定義之前找到該函數(shù)。

第 1 行,沒(méi)有拋出錯(cuò)誤,是因?yàn)檫@時(shí)變量 notyetdeclared 不存在嗎?

同樣的,notyetdeclared 被注冊(cè)到了標(biāo)識(shí)符,并在第1階段中初始化為 undefined ,因此不會(huì)拋出任何錯(cuò)誤。

最后,

第 4 行,notyetdeclared 已經(jīng)在全局作用域內(nèi)聲明了,為什么在第 9 行打印時(shí)還是 undefined 呢?

現(xiàn)在我們進(jìn)入函數(shù) hoisting 環(huán)境中。在第1階段中,notyetdeclared 被注冊(cè)并初始化為  undefined,因?yàn)樵谶@個(gè)詞法環(huán)境中,notyetdeclared 的變量還沒(méi)有被注冊(cè)。如果第 12 行不包含var 關(guān)鍵字,那么情況就不同了。

希望現(xiàn)在可以清楚地看到,在 JavaScript 中 Hoisting(提升) 只是我們用于解釋其背后原理的一個(gè)觀點(diǎn),從技術(shù)上來(lái)講,函數(shù)和變量并不會(huì)移動(dòng)到任何地方。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • JavaScript實(shí)現(xiàn)的鼠標(biāo)響應(yīng)顏色漸變效果完整實(shí)例

    JavaScript實(shí)現(xiàn)的鼠標(biāo)響應(yīng)顏色漸變效果完整實(shí)例

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)的鼠標(biāo)響應(yīng)顏色漸變效果,涉及javascript面向?qū)ο蠹笆录O(jiān)聽(tīng)、響應(yīng)機(jī)制相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • JS?Date時(shí)間格式化的方法

    JS?Date時(shí)間格式化的方法

    這篇文章主要介紹了JS?Date時(shí)間格式化的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-01-01
  • js寫一個(gè)字符串轉(zhuǎn)成駝峰的實(shí)例

    js寫一個(gè)字符串轉(zhuǎn)成駝峰的實(shí)例

    寫一個(gè)字符串轉(zhuǎn)成駝峰的方法,使用js代碼實(shí)現(xiàn),具體如下,感興趣的朋友可以了解下哈
    2013-06-06
  • 淺析javascript中的DOM

    淺析javascript中的DOM

    本文主要給大家簡(jiǎn)單介紹了是什么是DOM、動(dòng)態(tài)操作DOM元素的方法、使用jsjs操作樣式以及Form對(duì)象的簡(jiǎn)介,是個(gè)人對(duì)于javascript中的DOM的理解的總結(jié),推薦給小伙伴們。
    2015-03-03
  • 淺析$(function) ready和onload 的區(qū)別

    淺析$(function) ready和onload 的區(qū)別

    新手剛學(xué)習(xí)js和jq的時(shí)候難免會(huì)接觸題目所標(biāo)識(shí)的相關(guān)內(nèi)容,下面小編通過(guò)本教程給大家講解(function) ready和onload 的區(qū)別,感興趣的朋友一起看看吧
    2016-09-09
  • 鼠標(biāo)右擊事件代碼(asp.net后臺(tái))

    鼠標(biāo)右擊事件代碼(asp.net后臺(tái))

    本程序由一個(gè)js文件和aspx文件組成,沒(méi)有后臺(tái)CS代碼。
    2011-01-01
  • 全系IE支持Bootstrap的解決方法

    全系IE支持Bootstrap的解決方法

    用了bootstrap模版搭建的網(wǎng)站,在IE7中打不開(kāi),在IE8中背景圖片都不顯示,內(nèi)容排列也出現(xiàn)問(wèn)題,在IE9中表現(xiàn)的最好,在IE11中出現(xiàn)彈出層中的圖片無(wú)法顯示,那么這些兼容性怎么去解決
    2015-10-10
  • 理解JS綁定事件

    理解JS綁定事件

    這篇文章主要幫助大家深入理解JS綁定事件,介紹了六種JS綁定事件的情況,感興趣的小伙伴們可以參考一下
    2016-01-01
  • iOS微信H5頁(yè)面橡皮回彈效果的踩坑記錄

    iOS微信H5頁(yè)面橡皮回彈效果的踩坑記錄

    移動(dòng)端開(kāi)發(fā)時(shí),H5長(zhǎng)頁(yè)面在iOS系統(tǒng)中滑動(dòng)時(shí),當(dāng)頁(yè)面滑動(dòng)到頂部或底部時(shí),頁(yè)面還能夠上滑或下滑,手指離開(kāi)屏幕后回彈,這就時(shí)橡皮筋效果,這篇文章主要給大家介紹了關(guān)于iOS微信H5頁(yè)面橡皮回彈效果的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • JavaScript數(shù)組實(shí)現(xiàn)扁平化四種方法詳解

    JavaScript數(shù)組實(shí)現(xiàn)扁平化四種方法詳解

    扁平化,顧名思義就是減少?gòu)?fù)雜性裝飾,使其事物本身更簡(jiǎn)潔、簡(jiǎn)單,突出主題。數(shù)組扁平化,對(duì)著上面意思套也知道了,就是將一個(gè)復(fù)雜的嵌套多層的數(shù)組,一層一層的轉(zhuǎn)化為層級(jí)較少或者只有一層的數(shù)組
    2022-10-10

最新評(píng)論