【前端知識體系】瀏覽器

1事件循環機制

1.1多線程的瀏覽器和單線程的JavaScript

衆所周知,JS只有一個主線程,那麼在執行所有任務的時候只能一個一個來嗎?就像是排隊看病一樣,醫生一次只能接待一個病人。那麼如果這個病人需要去化驗,等待結果的這段時間醫生還是等待這個病人化驗嗎?還是會先接待後面的病人?JS有自己的機制來解決這個問題。

雖然JS是單線程的,但是瀏覽器是事件驅動的,一個瀏覽器中有多個常駐線程。

1.Js引擎線程:JavaScript引擎是基於事件驅動單線程執行的,JavaScript引擎一直等待着任務隊列中任務的到來,然後加以處理,瀏覽器無論什麼時候都只有一個JavaScript線程在運行JavaScript程序。

2.Gui渲染線程: GUI渲染線程負責渲染瀏覽器界面,當界面需要重繪(Repaint)或由於某種操作引發迴流(Reflow)時,該線程就會執行。但需要注意,GUI渲染線程與JavaScript引擎是互斥的,當JavaScript引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JavaScript引擎空閒時立即被執行。

3.事件觸發線程: 當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JavaScript引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeout、也可來自瀏覽器內核的其他線程如鼠標點擊、Ajax異步請求等,但由於JavaScript的單線程關係所有這些事件都得排隊等待JavaScript引擎處理(當線程中沒有執行任何同步代碼的前提下才會執行異步代碼)。

還會開闢一些其他線程,例如http請求線程等等(用完就關閉)

 

1.2 瀏覽器的事件循環(event loop)

1.函數入棧,當Stack中執行到異步事件的時候,就將他丟給WebAPIs,接着執行同步任務,直到Stack爲空;

2.在此期間WebAPIs完成這個事件,把回調函數放入CallbackQueue中等待(js主線程執行異步任務,就是在執行回調函數);

3.當執行棧爲空時,Event Loop把Callback Queue中的一個任務放入Stack中,回到第1步。

 

#stack 執行棧,JS主線程來處理

#Event Loop事件循環是由javascript宿主環境(像瀏覽器)來輪詢實現的;使得主線程從執行隊列中不斷獲取任務(異步事件的回調)。

#WebAPIs是由C++實現的瀏覽器創建的線程,處理諸如DOM事件、http請求、定時器等異步事件;

#JavaScript 的併發模型基於"事件循環";

#Callback Queue(Event Queue 或者 Message Queue) 任務隊列,存放異步事件的回調函數

 

2事件機制

2.1 Dom節點的刪除與事件綁定

在刪除了Dom節點的時候,是否需要手動刪除綁定在其上的事件。在刪除一個節點的時候,瀏覽器會將刪除掉的節點的兄弟指針和父指針置爲null,並沒有delete。所以此時,這個節點依然存在於內存中,事件依然存在。什麼時候,這個節點會被析構呢?當發生GC回收的時候,會將不存在引用的Dom節點的內存釋放掉,並刪除map裏面的數據。所以並不需要手動刪除事件。

2.2 Dom的Level 0 事件

指的是dom節點的onclick onfocus等屬性。

onClick 和 addEventLisener: onClick的綁定實際上仍然調用的是addEventLisener,只是在此之前會先clear掉上一次綁定的屬性事件。所以onClick和addEvnetLisener並不衝突。

1.onclick事件在同一時間只能指向唯一對象

2.addEventListener給一個事件註冊多個listener

3.addEventListener對任何DOM都是有效的,而onclick僅限於HTML

4.addEventListener可以控制listener的觸發階段,(捕獲/冒泡)。對於多個相同的事件處理器,不會重複觸發,不需要手動使用removeEventListener清除

5.IE9使用attachEvent和detachEvent

 

Dom.onClick(()=>console.log(‘第一次’)

Dom.onClick(()=>console.log(“第二次”)

只會觸發一次,輸出‘第二次’

 

Dom.addEventLisener(‘click’,()=>console.log(‘第一次’))

Dom.addEventLisener(‘click’,()=>console.log(‘第二次’))

會觸發兩次,依次觸發。

 

2.3 事件的捕獲目標冒泡

 

1.捕獲(Capture):事件對象(event object) 從 window 派發到 目標對象父級的過程。

2.目標(Target): 事件對象派發到目標元素時的階段,如果事件類型指示其不冒泡,那事件傳播將在此階段終止。

3.冒泡(Bubbling):和捕獲相反,是以目標對象父級到 window 的過程。

在任一階段調用 stopPropagation 都將終止本次事件的傳播

addEventLisener形式註冊的監聽事件接受參數以指定是否在捕獲階段觸發本次事件,默認值爲否(既冒泡階段)。以事件處理器註冊的事件在非捕獲階段觸發。

通過e.stopPropagation()可以阻止事件傳播。

2.4 瀏覽器的默認事件

例如點擊a標籤時候的跳轉,通過input提交表單等,可以通過e.preventDefault()進行阻止。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章