JS進階---事件循環

事件循環

//輸出結果是多少呢,先輸出'abc'還是先交叉輸出
//還是先輸出i呢
setTimeout(function func1() {
   console.log("abc")
 }, 0);
 for (var i = 0; i < 10000; i++) {
     console.log(i);
 }

概念

ps:最後有面試題哦

  1. 瀏覽器、JS、執行引擎的關係

JS:一門計算機語言,提供了表達程序邏輯的語法和實現基本功能的API

瀏覽器:JS語言的真實運行環境,又稱之爲JS的宿主環境

JS執行引擎:JS宿主環境(例如瀏覽器)中的一個功能模塊,用於解析並執行JS

它們的關係如下:

在這裏插入圖片描述

  1. 進程 和 線程

進程:當一個應用程序運行時,需要使用內存和CPU資源,這些資源需要向操作系統申請。操作系統以進程的方式來分配這些資源,一個進程就代表着一塊獨立於其他進程的內存空間。一個應用程序要運行,必須至少有一個進程啓動。進程的最大特點是獨立,一個進程不能隨意的訪問其他進程的資源。這就保證了多個程序在操作系統上運行互不干擾。

在這裏插入圖片描述

線程:可能要同時執行多個任務,每個任務需要在一個線程上運行,線程與線程之間相對獨立,但可以共享應用程序的進程數據。

在這裏插入圖片描述

  1. 如何理解JS的單線程

我們之所以稱JS爲單線程的語言,是因爲它的執行引擎只有一個線程,並且不會在執行期間開啓新的線程。而並非瀏覽器是單線程的。

單線程的應用程序具有以下的特點:

  • 易於學習和理解:所有代碼都是按照順序從上到下執行的
  • 易於掌控程序:由於代碼都按照順序執行,不會出現中斷,也沒有共享資源的爭奪問題,極大的降低了開發難度。
  • 更加合理的利用計算機資源:創建新的線程和銷燬線程都會耗費額外的CPU和內存資源,沒有良好的線程設計,將導致程序運行效率低下。而單線程的應用不受此影響

在這裏插入圖片描述

  1. JS如何處理多任務

任何一個程序在執行期間都可能會開啓多個任務,比如:

1). 任務1:程序啓動時開始進行一些操作
2). 任務2:開啓一個計時器,每隔一段時間去做一些事
3). 任務3:監聽按鈕是否被點擊,當按鈕被點擊後,去做一些事

由於JS的執行線程只有一個,因此,它通過異步的方式來解決這些任務

下面是單線程的異步和多線程的對比

多線程:

在這裏插入圖片描述
可以看到,如果以多線程的方式運行,會導致程序代碼在某些時候會有重疊執行的情況出現,如果這些代碼湊巧在使用共享數據,將難以控制最終的運行結果。

而使用異步的方式就解決了該問題:

在這裏插入圖片描述

可以看出,使用異步之後,所有的JS代碼都在單個線程中執行,不會出現多個任務同時執行的情況,自然就不會出現資源爭奪的問題。

  1. 同步代碼 和 異步代碼

同步代碼:程序啓動後,在JS執行線程上立即執行的任務代碼

異步代碼:收到宿主環境(瀏覽器)的其它線程通知,即將在JS執行線程上執行的代碼,例如計時器回調函數中的代碼,事件中的代碼。JS中的異步代碼往往放到一個函數中,該函數成爲異步函數,或者描述爲,該函數是異步的

  1. 執行棧

爲了保證JS代碼有序的執行,JS執行引擎使用執行棧來組織JS代碼

每當調用一個函數時,都會在執行棧中創建一個執行上下文,上下文中提供了函數執行需要的環境,創建了上下文之後,再執行函數

事件循環

事件循環是JS處理異步函數的具體方法

具體的做法是:

  1. 執行 執行棧 中的代碼
  2. 遇到一些特殊代碼交給瀏覽器的其他線程處理
  3. 將執行棧中的代碼全部執行完畢
  4. 從事件隊列中取出第一個任務放入執行棧,然後重複第1步

在這裏插入圖片描述

事件隊列在不同的宿主環境中有所差異,大部分宿主環境會將事件隊列進行細分。在瀏覽器中,事件隊列分爲兩種:

  • 宏任務(隊列):macroTask,計時器結束的回調、事件回調、http回調等等絕大部分異步函數進入宏隊列
  • 微任務(隊列):microTask,Promise.then, MutationObserver

在這裏插入圖片描述

當執行棧清空時,JS引擎首先會將微任務中的所有任務依次執行結束,如果沒有微任務,則執行宏任務。

如果上面文章都懂了,那麼來道題目開開胃吧!
這道題目要好好的思考一下,在這裏就不公佈答案了,可以自己運行一下看看答案正確與否

setTimeout(function func1() {
      console.log(1)
      a();
  }, 0)

  function a() {
      setTimeout(function func2() {
          console.log(2)
      }, 0)
      console.log(3)
  }

  a();

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