【JavaScript 學習--12】JS深入理解呼叫棧,事件迴圈機制,回撥佇列
最近研究JavaScript裡的函式事件這些到底是如何呼叫的,查閱了好些資料,特別是國外一些大牛寫的文章,啟發非常的大,於是打算對這些知識進行梳理。
基本知識
JS是什麼?
- JS是單執行緒,非阻塞,非同步,併發的語言
- JS有 呼叫棧,事件迴圈,回撥佇列,其它的APIs。
JS 在執行時
- JS在執行時(像V8引擎)有堆(記憶體分配)和棧(執行環境), 但是他們沒有 setTimeout, DOC 等,這些是瀏覽器的web APIs。
我們知道的JS在瀏覽器裡有:
- 執行時的V8(堆/棧)
- 瀏覽器提供web APIs,比如DOM, ajax, 和setTimeout
- 事件的回撥佇列,比如onClick, onLoad, onDone。
- 事件迴圈
JS的單執行緒(single thread)
:僅僅是指JS程式碼執行在單執行緒裡面。呼叫棧(call stack)
:又稱執行環境(execution contexts), 當函式或者程式呼叫的時候,就把該函式push到呼叫棧,結束時候,就從棧頂端移除。遵循FILO(先進後出)原則。注意
:呼叫棧有個最大呼叫幀,chrome 瀏覽器最大支援16000個呼叫幀,超過後,會報“RangeError:Maximum call stack size exceeded”
堆(Heap)
: 記憶體分配(memory allocation)的一塊空間。JS的引用型別的值是放在堆記憶體的。回撥佇列(callback Queue)
事件迴圈(event loop)
: 事件迴圈不斷的輪詢檢測呼叫棧是否為空?如果不為空,就等待呼叫棧為空,否則就把回撥佇列列表裡的事件放到呼叫棧執行。迴圈直到回撥佇列列表為空。
同步函式呼叫棧機制
我們以一個例子來進行同步函式執行的機制, 有兩個函式foo,和bar,bar內部呼叫foo。
function foo(a, b) {
console.log("in foo");
return a * b;
}
function bar(y) {
var x = 10;
console.log("in bar" );
return foo(x, y);
}
console.log(bar(5));
以上程式碼執行順序如下:
- 最先進入
console.log(bar(5));
因此它被推送到呼叫棧。 console.log(bar(5))
;呼叫函式bar(5), 等待bar(5)的返回結果,於是把bar(5)推送到呼叫棧頂部。- 函式bar(5)裡有
console.log("in bar");
於是推送console.log("in bar");
到棧頂。 console.log("in bar");
執行完成返回,然後將console.log("in bar");
從棧頂移除。- 接著執行
return foo(x, y);
,這是呼叫foo(x, y)
,把foo(x, y)
推入到呼叫棧。 - 執行
console.log("in foo");
推入棧頂,結束,移除棧。 - 執行
return a * b;
呼叫a * b
,推送a * b
到棧頂,a * b
執行完後,出棧。 - 接著 return 10+5的結果返回給bar函式的foo(10, 5),這樣foo(x,y)函式結束執行,foo(x,y)從呼叫棧移除。
- 接著bar(y)函式return foo(10, 5)的值給bar(5),這樣bar(5)執行結束,從呼叫棧中移除。
- 最後
console.log(bar(5));
打印出15值,console.log呼叫完成,將console.log移除棧。這時呼叫棧就為空了,呼叫結束。
執行順序請參考下圖:
非同步呼叫的事件迴圈機制
我們以setTimeout 為例, 有這樣程式碼,用兩個不同的timeout來闡述setTimeout的事件迴圈機制。
console.log("1");
setTimeout(function secondTimeout() {
console.log("2");
}, 5000);
setTimeout(function firstTimeout() {
console.log("3");
}, 0);
console.log("4.");
以上程式碼執行後列印順序是: 1, 4, 3, 2
以上程式碼執行機制如下:
1. 程式碼執行的console.log("1");
將其push到呼叫棧,緊接著完成,從呼叫棧刪除
2. 接著呼叫setTimeout的secondTimeout
,將其push到呼叫棧,由於setTimeout是web API,因此web API 處理secondTimeout這個事件,並從呼叫棧中移除,並且在web API中開始等待5秒。
3. 接著呼叫setTimeout的firstTimeout
,將其push到呼叫棧,由於setTimeout是web API,因此web API 處理這個firstTimeout
事件, 由於等待是0秒,於是將firstTimeout
推送到回撥佇列,等待呼叫棧的執行(遵循先進先出
原則)。這時事件迴圈(event loop)機制開始執行,檢查這時呼叫棧不為空?繼續排隊等待:把回撥佇列列表的第一個佇列推送到呼叫棧執行。由於此時,呼叫棧還要繼續執行console.log("4.");
所以繼續等待呼叫棧結束。
4. 接著console.log("4.");
列印完成,這時已經是到程式碼執行尾部,沒有主程式碼運行了,呼叫棧為空。事件迴圈機制檢查到呼叫棧為空後,將第一個在callback Queue裡的函式firstTimout() 推送到呼叫棧執行,並呼叫console.log(3)
。結束後釋放呼叫棧。
5. 當此時呼叫棧為空時,event loop繼續將callback Queue例表裡的其他佇列一個一個push到呼叫棧去執行。如果此時回撥佇列例表裡有多個佇列排隊,那麼就安裝此迴圈,直到全部完成為止。
promise的事件迴圈機制
參考資料
相關推薦
【JavaScript 學習--12】JS深入理解呼叫棧,事件迴圈機制,回撥佇列
最近研究JavaScript裡的函式事件這些到底是如何呼叫的,查閱了好些資料,特別是國外一些大牛寫的文章,啟發非常的大,於是打算對這些知識進行梳理。 基本知識 JS是什麼? JS是單執行緒,非阻塞,非同步,併發的語言 JS有 呼叫棧,事件迴圈,回撥
【JavaScript 學習--05】Nodejs之如何呼叫 cmd 命令
/*For getting data from PR system API*/ var express = require('express'); var router = express.Rout
【Javascript學習筆記】【js執行緒實戰— —實現隨機速度的打字機效果】
目錄 隨機速度的打字機效果 效果 程式碼 html部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF
【JavaScript學習筆記】1:js的書寫,顯示資料,變數,函式
JavaScript描述的是網頁的行為,可以直接改變HTML而改變網頁的內容,或者提供和使用者的互動。 js寫在哪裡 ①直接寫入HTML JavaScript可以寫在HTML的script雙標籤裡,一般把這個雙標籤放在HEAD頭裡: <
【JavaScript學習筆記】if使用
document asc cnblogs class body 學習筆記 lang div var <html> <body> <script language="JavaScript">
【JavaScript學習筆記】鼠標樣式
右箭頭 javascrip script mov wait bsp cursor and ossh style="cursor:hand" 手形 style="cursor:crosshair" 十字形 style="cursor:text" 文本
【JavaScript學習筆記】調用google搜索
alt href blog ddl ear input arch -c html <html> <form method=get action="http://www.google.com/search"> <a
【JavaScript學習筆記】畫圖
ctype net ner cli onmouseup move con cursor bsp <!DOCTYPE HTML> <html> <head> <script type="text/ja
【JavaScript學習筆記】hello world
div color html pre 學習筆記 bsp body pan class <html> <body> <script language="JavaScript"> al
【JavaScript學習筆記】點擊消失
hid his script click fun bsp logs document query <!DOCTYPE html> <html> <head> <script type="text/j
【譯】理解Javascript函式執行—呼叫棧、事件迴圈、任務等
原文作者:Gaurav Pandvia 原文連結:medium.com/@gaurav.pan… 文中部分連結可能需要梯子。 歡迎批評指正。 現如今,web開發者(我們更喜歡被叫做前端工程師)用一門指令碼語言就能做任何事情,從提供瀏覽器中的互動,到開發電腦遊戲、桌面工具、跨平臺移動
【Javascript學習筆記】【DOM實戰— —jQ實現點選任意位置關閉某處的效果(常用於模態框後面的遮罩層)】
【Javascript學習筆記】 目錄 目錄 原理 效果 程式碼 實戰程式碼 快捷連結 點選任意位置關閉某處 而且點選對應處並不會hide掉自己 原理
【MyBatis學習12】MyBatis中的一級快取
快取的作用是減輕資料庫的壓力,提高資料庫的效能的。mybatis中提供了一級快取和二級快取,先來看一下兩個快取的示意圖: 從圖中可以看出: 一級快取是SqlSession
【redis 學習系列】API的理解與使用
全局命令 時間復雜度 總數 鍵值 seconds clas mil height 同時 Redis提供了5種數據結構,以下介紹一些預備知識以及Redis的5種數據結構 1、預備知識 1.1 全局命令 Redis的5種數據結構,它們是鍵值對中的值,對於鍵來說有一些通用的
【Java學習筆記】66:認識Java中的Reflection(反射)機制,獲取類的屬性和方法
反射部分一直欠著,現在學框架和Servlet必須要學一下了。最近學習Struts2框架和Servlet時候,很多地方直接給出類名就可以去使用了,如在web.xml中配置Filter時: <filter> <filter-name&
JS-呼叫棧、事件迴圈、訊息佇列(也叫任務隊和回撥佇列)、作業佇列(微任務佇列)
一:呼叫棧是個什麼鬼東西,它具有棧的屬性--後進先出 先看一段簡單的JS程式碼: const second = function(){ console.log('hello there'); } const first = function() { console.log('hi,first'); secon
JS瀏覽器賭博網站平臺出租事件迴圈機制
程序、執行緒程序賭博網站平臺出租【大神原始碼論壇】dsluntan.com 【布丁原始碼論壇】budingbbs.com 企娥3393756370是系統分配的獨立資源,是 CPU 資源分配的基本單位,程序是由一個或者多個執行緒組成的。執行緒是程序的執行流,是CPU排程和分派
【Spark深入學習 -12】Spark程序設計與企業級應用案例02
提升 算子 lin count() roi println groupby 工作問題 衍生 ----本節內容------- 1.遺留問題答疑 1.1 典型問題解答 1.2 知識點回顧 2.Spark編程基礎 2.1 Spark開發四部曲 2.2 RDD典型實例
【Java】「深入理解Java虛擬機器」學習筆記(1) - Java語言發展趨勢
這本書寫的比較早,現在這些功能都已經不同程度的實現了。 1、模組化 JDK9之前的版本都是一個整體,使用者可能只需要使用一個小功能,但他不得不下載整個JDK。不能滿足定製化需求,顯然Java語言的發展因此大大受限。 所以,Sun公司在OpenJDK建立了一個Jigsaw(拼圖)的專案來推動模
【Java】「深入理解Java虛擬機器」學習筆記(2)-記憶體管理
一、執行時資料區 JVM在執行Java程式的時候,將其執行時資料區劃分為若干不同區域。它們的用途和建立及銷燬的時間不同。 1、程式計數器(Program Counter Register) 是一塊很小的記憶體空間。當執行緒執行的是Java方法,它記錄的是當前正在執行的