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