摘要:還請(qǐng)同學(xué)跟我多多探討關(guān)于修改是異步還是同步的問(wèn)題先來(lái)看代碼上述代碼的結(jié)果完全就是同步的表現(xiàn),如果是異步的話,毫無(wú)疑問(wèn),第一個(gè)下的每個(gè)內(nèi)容都應(yīng)該是,第二個(gè)也應(yīng)該是。
回 @bf 同學(xué)
本篇文章不是筆記也不是心得,而是關(guān)于一個(gè)問(wèn)題的討論,問(wèn)題最初出現(xiàn)于https://segmentfault.com/q/1010000005630545?_ea=903562
由于 @bf 同學(xué)不方便加QQ/微信,而這個(gè)問(wèn)題又比較大,在問(wèn)答評(píng)論里不好描述清楚,so,趁著周末專門寫了一篇文章來(lái)回應(yīng) @bf 同學(xué)
@bf 同學(xué),提到了一個(gè)觀點(diǎn):對(duì)DOM的修改永遠(yuǎn)是異步的
當(dāng)時(shí)就震驚到我了(可能技術(shù)不達(dá)標(biāo),少見(jiàn)多怪的緣故,哈哈)
說(shuō)實(shí)話,干了好幾年開(kāi)發(fā),第一次明確地聽(tīng)到有人這樣說(shuō),根據(jù)自己看的書及一些javascript編程經(jīng)驗(yàn)來(lái)說(shuō),起初我認(rèn)為是錯(cuò)誤的。
然后看了看 @bf 同學(xué)的回復(fù),能自圓其說(shuō),還說(shuō)的頭頭是道,所以我真的以為對(duì)DOM的修改永遠(yuǎn)是異步的是正確的。然后懷著震驚的心情(因?yàn)楦?jīng)驗(yàn)相違背),還寫了一篇博客記錄http://www.liyanshan.com/2016/06/09/%E5%AF%B9DOM%E7%9A%84%E4%BF%AE%E6%94%B9%E6%B0%B8%E8%BF%9C%E9%83%BD%E6%98%AF%E5%BC%82%E6%AD%A5%E7%9A%84/
經(jīng)過(guò)這么些天的發(fā)酵和消化,覺(jué)得對(duì)這個(gè)觀點(diǎn)又回到了最初的認(rèn)識(shí)(即這個(gè)觀點(diǎn)是錯(cuò)的)。
還請(qǐng) @bf 同學(xué)跟我多多探討 !
關(guān)于javascript修改dom是異步還是同步的問(wèn)題:
先來(lái)看代碼:
上述代碼的結(jié)果完全就是同步的表現(xiàn),如果是異步的話,毫無(wú)疑問(wèn),第一個(gè)ul下的li每個(gè)內(nèi)容都應(yīng)該是5,第二個(gè)也應(yīng)該是5。
這是數(shù)學(xué)中的反證法。即一個(gè)命題,哪怕我找出一個(gè)特例(何況我能找出很多例子)能推翻這個(gè)命題,那么這個(gè)命題就不成立。
@bf 同學(xué)可能會(huì)說(shuō)了,他也用反證法,比如script標(biāo)簽的加載,來(lái)證明DOM修改是異步的
但是這個(gè)特例的問(wèn)題在于:
把下載的異步性當(dāng)成了DOM修改的異步性
script標(biāo)簽加載是異步的,因?yàn)橐呔W(wǎng)絡(luò)(比如走網(wǎng)絡(luò)的ajax和圖片下載等都是異步的,當(dāng)然ajax也可以寫成同步的),也就是說(shuō),瀏覽器開(kāi)了一個(gè)線程下載要用的script,但是馬上返回(交給HTTP請(qǐng)求線程就不管了,請(qǐng)求結(jié)束,請(qǐng)求線程會(huì)把結(jié)果放入事件隊(duì)列里),接著執(zhí)行或下載其他部分。其實(shí)這個(gè)問(wèn)題我在引起這個(gè)討論的問(wèn)題上已經(jīng)回答了(可能回答的沒(méi)有那么清楚)。
然后又陸陸續(xù)續(xù)地看了一些書,查了一些資料,問(wèn)了一些大牛,越來(lái)越堅(jiān)信DOM修改是同步的
JavaScript異步編程第一章 - 異步的I/O函數(shù)(1.2.1)
這個(gè)也符合我最初跟 @bf 同學(xué)的解釋:修改DOM是同步的,但是渲染是異步的。因?yàn)镴avaScript引擎線程跟GUI渲染線程是互斥的,即我執(zhí)行的時(shí)候,你就靠邊站,我執(zhí)行完你才能執(zhí)行
詳見(jiàn)我2014年寫的一篇關(guān)于異步的文章(當(dāng)時(shí)就是記錄一下心得與筆記,也不會(huì)自己搭博客,也不會(huì)MD,所以請(qǐng) @bf 同學(xué)湊合看)http://blog.sina.com.cn/s/blog_6fd55a970102v64x.html
在群里提問(wèn)
這個(gè)其實(shí)就相當(dāng)于回答了js是同步修改的。。因?yàn)檫@是三個(gè)異步函數(shù)!
而 @bf 同學(xué)在后面的回復(fù)中,提到了一篇文章https://leozdgao.me/why-dom-slow/,額,我看了看這篇文章,發(fā)現(xiàn)其實(shí)我今年年初就看過(guò)了,當(dāng)時(shí)貌似是用瀏覽器重排和重繪搜索到的。。
這篇文章主要是講 重排和重繪及性能優(yōu)化一類的知識(shí)。
@bf 同學(xué)可能受到這句話的影響:
一般情況下,瀏覽器的layout是lazy的,也就是說(shuō):在js腳本執(zhí)行時(shí),是不會(huì)去更新DOM的,任何對(duì)DOM的修改都會(huì)被暫存在一個(gè)隊(duì)列中,在當(dāng)前js的執(zhí)行上下文完成執(zhí)行后,會(huì)根據(jù)這個(gè)隊(duì)列中的修改,進(jìn)行一次layout。
這個(gè)其實(shí)說(shuō)明不了修改DOM永遠(yuǎn)是異步的,這個(gè)是JavaScript引擎實(shí)現(xiàn)層面上的知識(shí),是對(duì)js修改DOM的優(yōu)化,它放入的隊(duì)列其實(shí)不是事件隊(duì)列,如果放到了事件隊(duì)列中,才是異步的。。C++實(shí)現(xiàn)一個(gè)隊(duì)列是何其簡(jiǎn)單啊!js實(shí)現(xiàn)隊(duì)列更簡(jiǎn)單!只是實(shí)現(xiàn)層面的東西,對(duì)程序猿都是透明的。。所以沒(méi)啥可說(shuō)的。只能幫助我們理解重排和重繪的機(jī)制,而不能得出修改DOM永遠(yuǎn)是異步的結(jié)論。。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/79774.html
摘要:關(guān)于異步應(yīng)該很多地方都說(shuō)過(guò),是單線程的,嚴(yán)格的說(shuō),是指引擎中負(fù)責(zé)解釋和執(zhí)行代碼的線程只有一個(gè),除此之外,其實(shí)還有事件觸發(fā)線程請(qǐng)求線程等,因此,應(yīng)該說(shuō)同步是單線程可能更準(zhǔn)確些。 作者:心葉時(shí)間:2019-03-08 09:45 我的理解 先列出我的理解,然后再?gòu)木唧w的例子中說(shuō)明: DOM操作本身應(yīng)該是同步的(當(dāng)然,我說(shuō)的是單純的DOM操作,不考慮ajax請(qǐng)求后渲染等) DOM操作之后導(dǎo)...
摘要:根本原因在于,并不是真正意義上的異步操作,它只是模擬了異步的行為。而合成事件和生命周期函數(shù)中,是受控制的,其會(huì)將設(shè)置為,從而走的是類似異步的那一套。總結(jié)此處總結(jié)是直接引用了只在合成事件和鉤子函數(shù)中是異步的,在原生事件和中都是同步的。 如何使用setState 在 React 日常的使用中,一個(gè)很重要的點(diǎn)就是,不要直接去修改 state。例如:this.state.count = 1是無(wú)...
摘要:主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為事件循環(huán)。上面也提到,在到達(dá)指定時(shí)間時(shí),定時(shí)器就會(huì)將相應(yīng)回調(diào)函數(shù)插入任務(wù)隊(duì)列尾部。這就是定時(shí)器功能。關(guān)于定時(shí)器的重要補(bǔ)充定時(shí)器包括與兩個(gè)方法。 一、引子 本文介紹JavaScript運(yùn)行機(jī)制,這一部分比較抽象,我們先從一道面試題入手: console.log(1); setTimeout(function()...
摘要:主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為事件循環(huán)。上面也提到,在到達(dá)指定時(shí)間時(shí),定時(shí)器就會(huì)將相應(yīng)回調(diào)函數(shù)插入任務(wù)隊(duì)列尾部。這就是定時(shí)器功能。關(guān)于定時(shí)器的重要補(bǔ)充定時(shí)器包括與兩個(gè)方法。 一、引子 本文介紹JavaScript運(yùn)行機(jī)制,這一部分比較抽象,我們先從一道面試題入手: console.log(1); setTimeout(function()...
摘要:主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為事件循環(huán)。上面也提到,在到達(dá)指定時(shí)間時(shí),定時(shí)器就會(huì)將相應(yīng)回調(diào)函數(shù)插入任務(wù)隊(duì)列尾部。這就是定時(shí)器功能。關(guān)于定時(shí)器的重要補(bǔ)充定時(shí)器包括與兩個(gè)方法。 一、引子 本文介紹JavaScript運(yùn)行機(jī)制,這一部分比較抽象,我們先從一道面試題入手: console.log(1); setTimeout(function()...
閱讀 3779·2021-11-25 09:43
閱讀 2199·2021-11-23 10:13
閱讀 831·2021-11-16 11:44
閱讀 2379·2019-08-29 17:24
閱讀 1391·2019-08-29 17:17
閱讀 3486·2019-08-29 11:30
閱讀 2590·2019-08-26 13:23
閱讀 2350·2019-08-26 12:10