亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

[譯]JavaScript的調(diào)用棧、回調(diào)隊(duì)列和事件循環(huán)

YancyYe / 989人閱讀

摘要:在這個(gè)視頻中,將的調(diào)用?;卣{(diào)隊(duì)列和事件循環(huán)的內(nèi)容講的很清晰。調(diào)用??梢酝锩娣艝|西,可以在事件結(jié)束的時(shí)候把回調(diào)函數(shù)放進(jìn)回調(diào)隊(duì)列,然后是事件循環(huán)。為的時(shí)候這個(gè)過(guò)程看起來(lái)可能不明顯,除非考慮到調(diào)用棧的執(zhí)行環(huán)境和事件循環(huán)的情況。

譯者按
這篇文章可以看做是對(duì)Philip Roberts 2014年在JSConf演講的《What the heck is the event loop anyway?》的一個(gè)總結(jié)。
建議先看Philip Roberts的這個(gè)演講然后再閱讀本篇文章。這哥們兒的演講語(yǔ)言幽默風(fēng)趣,內(nèi)容通俗易懂,非常值得一看。

在這個(gè)視頻中,Philip Roberts將JavaScript的調(diào)用棧、回調(diào)隊(duì)列和事件循環(huán)的內(nèi)容講的很清晰。所以你可以隨意的跳過(guò)這篇文章,花上一個(gè)半小時(shí)去看視頻。當(dāng)然如果你愿意讀一下我的這篇文章那也不是不可以。

什么是JavaScript

什么是JavaScript呢?列舉一些關(guān)鍵詞就是:

他是單線程的、非阻塞的、異步的并發(fā)語(yǔ)言

他有一個(gè)調(diào)用棧,一個(gè)事件循環(huán),一個(gè)回調(diào)隊(duì)列,還有一些api和別的東西

如果你像我一樣(或者像Philip Roberts)對(duì)此懵逼的話,這些話本身并沒(méi)不意味著什么。那我們就來(lái)剖析一下。

JavaScript運(yùn)行時(shí)

JavaScript運(yùn)行時(shí)(像V8引擎)擁有一個(gè)堆(內(nèi)存分配用的)和棧(執(zhí)行上下文)。但是他沒(méi)有setTimeout、DOM等。這些是瀏覽器提供的Web APIs。

我們了解的JavaScript

瀏覽器中的JavaScript擁有:

一個(gè)像V8引擎一樣的運(yùn)行時(shí)(提供堆棧)

瀏覽器提供的Web APIs,例如:DOMAJAXsetTimeout

一個(gè)為各種事件回調(diào)準(zhǔn)備的回調(diào)隊(duì)列,例如:onClick、onLoadonDone

一個(gè)事件循環(huán)

什么是調(diào)用棧

JavaScript是單線程的,意味著他有一個(gè)多帶帶的調(diào)用棧,意味著他一次能做一件事。調(diào)用?;旧暇褪且粋€(gè)記錄程序執(zhí)行位置的數(shù)據(jù)結(jié)構(gòu)。如果程序進(jìn)入了一個(gè)函數(shù),那就往這個(gè)棧里面塞些東西。如果程序從一個(gè)函數(shù)中return了,那就從棧頂彈出一些東西。

當(dāng)我們的程序報(bào)錯(cuò)的時(shí)候,我們會(huì)在控制臺(tái)看到調(diào)用棧信息。報(bào)錯(cuò)的時(shí)候我們可以看到棧的狀態(tài)(被調(diào)用的那個(gè)函數(shù)的)。

阻塞

這涉及到一個(gè)重要的問(wèn)題:程序運(yùn)行的很慢的時(shí)候發(fā)生了什么?換句話說(shuō),就是程序阻塞了。阻塞并沒(méi)有嚴(yán)格的定義。實(shí)際上就是程序執(zhí)行慢。執(zhí)行console.log不慢,但是一個(gè)從1到1,000,000,000的while循環(huán),圖像處理或者網(wǎng)絡(luò)請(qǐng)求這些操作的執(zhí)行就比較費(fèi)時(shí)了。這些執(zhí)行慢的東西堆在一起就發(fā)生了阻塞。

因?yàn)镴avaScript是單線程的,我們發(fā)起一個(gè)網(wǎng)絡(luò)請(qǐng)求就不得不一直等到他結(jié)束。這在瀏覽器中就是個(gè)問(wèn)題--當(dāng)我們等這個(gè)請(qǐng)求的時(shí)候,瀏覽器就發(fā)生了阻塞(我們不能做點(diǎn)擊、提交表單等操作)。解決這個(gè)問(wèn)題的方法就是使用異步回調(diào)。

并發(fā),看到這個(gè)詞的時(shí)候我們會(huì)發(fā)現(xiàn)上面有一個(gè)地方說(shuō)的不對(duì)

JavaScript一次只能做一件事情的說(shuō)法是不對(duì)的。正確的說(shuō)法應(yīng)該是:JavaScript的運(yùn)行時(shí)一次只能做一件事。他不能一邊發(fā)ajax請(qǐng)求一邊運(yùn)行別的代碼,也不能在執(zhí)行別的代碼時(shí)候運(yùn)行一個(gè)定時(shí)器。但是我們可以并發(fā)的做這些事。因?yàn)闉g覽器不僅僅是一個(gè)運(yùn)行時(shí)(還記得上面那個(gè)渣渣畫(huà)質(zhì)的圖嗎?)。

調(diào)用??梢酝鵚eb APIs里面放東西,Web APIs可以在事件結(jié)束的時(shí)候把回調(diào)函數(shù)放進(jìn)回調(diào)隊(duì)列,然后是事件循環(huán)。最終我們進(jìn)入事件循環(huán),這是這個(gè)過(guò)程中最簡(jiǎn)單的部分,他有一個(gè)非常簡(jiǎn)單的工作:看看調(diào)用棧,瞅瞅回調(diào)隊(duì)列,如果調(diào)用??臻e了,就把回調(diào)隊(duì)列中的第一個(gè)函數(shù)取出來(lái)丟進(jìn)調(diào)用棧讓他執(zhí)行(這就回到了JavaScript的地盤(pán),回到了V8的內(nèi)部)。

整個(gè)串起來(lái)

Philip搞了一個(gè)的碉堡的工具來(lái)可視化這個(gè)過(guò)程,這玩意兒叫Loupe。這是一個(gè)能夠把JavaScript運(yùn)行時(shí)可視化的工具。

我們用它來(lái)看一個(gè)簡(jiǎn)單的例子:在一個(gè)異步的setTimeout回調(diào)中用console.log在控制臺(tái)打些log出來(lái)。

整個(gè)過(guò)程到底都發(fā)生了什么呢?我們來(lái)看一下:

執(zhí)行進(jìn)入console.log("Hi");函數(shù),因此這個(gè)函數(shù)被丟進(jìn)了調(diào)用棧里。

console.log("Hi");函數(shù)return了,因此他就被彈出了棧頂。

執(zhí)行進(jìn)入setTimeout函數(shù),因此這個(gè)函數(shù)被丟進(jìn)了調(diào)用棧里。

setTimeoutWeb APIs的一部分,因此Web APIs處理了他,并且等了2秒

繼續(xù)執(zhí)行腳本,進(jìn)入console.log("EvenyBody")函數(shù),把他也丟進(jìn)調(diào)用棧。

console.log("EvenyBody")函數(shù)return了,所以把他從棧頂彈出去

2秒的定時(shí)已經(jīng)完成了,所以就把對(duì)應(yīng)的回調(diào)函數(shù)放到回調(diào)隊(duì)列里。

事件循環(huán)檢查調(diào)用棧是否為空,如果非空的話,他就等著。因?yàn)檎{(diào)用?,F(xiàn)在是空的,所以把回調(diào)隊(duì)列中的回調(diào)函數(shù)丟進(jìn)調(diào)用棧。

console.log("There")函數(shù)返回了,因此把他從棧頂彈出去(譯者按:原文為console.log("Everybody"),應(yīng)為書(shū)寫(xiě)錯(cuò)誤)。

有趣的一點(diǎn)是:setTimeout(function(...), 0)的情況。setTimeout為0的時(shí)候這個(gè)過(guò)程看起來(lái)可能不明顯,除非考慮到調(diào)用棧的執(zhí)行環(huán)境和事件循環(huán)的情況。基本上都會(huì)推遲到調(diào)用棧為空才執(zhí)行。

考慮UI渲染的性能的情況

為了回到了我們?nèi)粘L幚淼腢I層,我們需要考慮渲染問(wèn)題。瀏覽器受到我們?cè)贘avaScript中所做操作的影響,他可能每隔16.6ms重繪一次屏幕(60幀/秒)。但是調(diào)用棧還有代碼在執(zhí)行的話,他實(shí)際上是沒(méi)法做重繪的。

就像Philip說(shuō)的一樣:

當(dāng)大家說(shuō)不要"阻塞事件循環(huán)"的時(shí)候,他們實(shí)際上是說(shuō):不要把耗費(fèi)時(shí)間長(zhǎng)的代碼放進(jìn)調(diào)用棧,因?yàn)槟阋@么搞的話,瀏覽器就不能做他該做的事了,比如說(shuō)給你搞一個(gè)漂亮流暢的UI。

Philip Roberts “What the Heck Is the Event Loop Anyway”

舉個(gè)例子,滾動(dòng)的處理函數(shù)觸發(fā)多了會(huì)讓UI變得卡頓。順便說(shuō)一句,這是我聽(tīng)過(guò)的對(duì)防抖最清楚的解釋了,這就是你要做到的“不要阻塞事件循環(huán)”(那就是我們只在滾動(dòng)處理函數(shù)被觸發(fā)x次后才執(zhí)行那些耗時(shí)的操作)。

結(jié)語(yǔ)

總之,這就是《What the heck is the event loop anyway?》的答案。Philip的演講很好的幫我理解了什么是JavaScript,什么不是,哪個(gè)部分是運(yùn)行時(shí),哪個(gè)部分是瀏覽器的和我們?cè)撛鯓佑行У氖褂檬录h(huán)。好好看看這個(gè)視頻吧。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/101789.html

相關(guān)文章

  • []你并不知道Node

    摘要:?jiǎn)栴}什么是調(diào)用棧并且它是的一部分么調(diào)用棧當(dāng)然是的一部分。為什么理解是重要的因?yàn)槟阍诿總€(gè)進(jìn)程中只能獲取一個(gè)調(diào)用棧。它是一個(gè)從事件隊(duì)列中跳去事件的循環(huán)并且將它們的回調(diào)壓入到調(diào)用棧中。當(dāng)調(diào)用棧為空的時(shí)候,事件循環(huán)可以決定下一步執(zhí)行哪一個(gè)。 你并不知道Node 原文:You don’t know Node 譯者:neal1991 welcome to star my articles-tra...

    miqt 評(píng)論0 收藏0
  • JavaScript 工作原理之一-引擎,運(yùn)行時(shí),調(diào)用()

    摘要:本章會(huì)對(duì)語(yǔ)言引擎,運(yùn)行時(shí),調(diào)用棧做一個(gè)概述。調(diào)用棧只是一個(gè)單線程的編程語(yǔ)言,這意味著它只有一個(gè)調(diào)用棧。查看如下代碼當(dāng)引擎開(kāi)始執(zhí)行這段代碼的時(shí)候,調(diào)用棧會(huì)被清空。之后,產(chǎn)生如下步驟調(diào)用棧中的每個(gè)入口被稱(chēng)為堆棧結(jié)構(gòu)。 原文請(qǐng)查閱這里,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原...

    Betta 評(píng)論0 收藏0
  • JavaScript 工作原理之一-引擎,運(yùn)行時(shí),調(diào)用()

    摘要:本章會(huì)對(duì)語(yǔ)言引擎,運(yùn)行時(shí),調(diào)用棧做一個(gè)概述。調(diào)用棧只是一個(gè)單線程的編程語(yǔ)言,這意味著它只有一個(gè)調(diào)用棧。查看如下代碼當(dāng)引擎開(kāi)始執(zhí)行這段代碼的時(shí)候,調(diào)用棧會(huì)被清空。之后,產(chǎn)生如下步驟調(diào)用棧中的每個(gè)入口被稱(chēng)為堆棧結(jié)構(gòu)。 原文請(qǐng)查閱這里,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原...

    Alex 評(píng)論0 收藏0
  • JavaScript 如何工作:對(duì)引擎、運(yùn)行時(shí)、調(diào)用概述

    摘要:調(diào)用棧是一種數(shù)據(jù)結(jié)構(gòu),它記錄了我們?cè)诔绦蛑械奈恢?。?dāng)從這個(gè)函數(shù)返回的時(shí)候,就會(huì)將這個(gè)函數(shù)從棧頂彈出,這就是調(diào)用棧做的事情。而且這不是唯一的問(wèn)題,一旦你的瀏覽器開(kāi)始處理調(diào)用棧中的眾多任務(wù),它可能會(huì)停止響應(yīng)相當(dāng)長(zhǎng)一段時(shí)間。 原文地址: https://blog.sessionstack.com... PS: 好久沒(méi)寫(xiě)東西了,最近一直在準(zhǔn)備寫(xiě)一個(gè)自己的博客,最后一些技術(shù)方向已經(jīng)敲定了,又可以...

    Warren 評(píng)論0 收藏0
  • 理解異步JavaScript

    摘要:當(dāng)函數(shù)結(jié)束,將會(huì)被從調(diào)用棧移出。事件循環(huán)事件循環(huán)的責(zé)任就是查看調(diào)用棧并確定調(diào)用棧是否為空。事件循環(huán)會(huì)再次檢查調(diào)用棧是否為空,如果為空的話,它會(huì)把事件回調(diào)壓入棧中,然后回調(diào)函數(shù)則被執(zhí)行。 寫(xiě)在文章前 這篇文章是翻譯自Sukhjinder Arora的Understanding Asynchronous JavaScript。這篇文章描述了異步和同步JavaScript是如何在運(yùn)行環(huán)境中,...

    ixlei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<