# JavaScript — Heap, Stack, Event-loops and Callback Queue * 網頁的運行 * 名詞解說 * 實際測試:分解程式碼 * 關於setTimeout的毫秒數 ## ### 網頁的運行 簡單提及網頁的運行方式, 其中最重要的是關於JavaScript的兩種特性,分別為單線程語言(single thread)和同步執行(synchronous)。 這兩種特性說明了Javascript的運行環境會由上到下的執行程式,並且一次只處理一件事,做完一件事才接著做下一件。 >那這樣我們的網頁是如何處理繁複的資料與程式,並呈現到網頁上的呢? 因為瀏覽器不僅僅只有Javascript的運行環境,它提供了許多webAPIs,我們會透過程式的呼叫來做運用,舉例來說,像是常見的`setTimeout`,`ajax(XMLHttprequest)`,當瀏覽器接收到這些代碼時,就會被移動到webAPIs執行,而不會阻擋到主程式。也就是達到非同步執行程式(asynchronous)的效果。 >所以說這個非同步實際上是如何被運行的呢?讓我們接著看下去 ... ### 名詞解說 <font color=red>`Heap`</font>:是一個拿來存放程式中已宣告之變數、函式等的空間。 <font color=red>`Stack`</font>:程式中要執行之函式跳進去的地方,執行完即跳出,具有後進先出(Last in First out)的性質。 <font color=red>`WebAPIs`</font>:當要執行非同步程式時,瀏覽器會在這邊開始執行,不會影響到主程式,執行完畢後不會直接被送到Stack,而是被送到callback Queue排隊等待。 <font color=red>`Callback Queue / Task Queue`</font>:是儲放非同步程式執行完成的空間,等待被丟進Stack執行。 <font color=red>`Event Loop`</font>:Event Loop 會持續查看 Stack 是否都執行完空下來了,如果是的話就會把 Callback Queue 裡面的任務依序丟進 Stack 去做執行。 將以上的流程以圖像化呈現,大致上是這樣子的  ## ### 實際測試:分解程式碼 這邊以一段簡短的程式碼作為實例  程式執行的結果會是  >這五秒間背後的程式是如何被運作的呢?這裡我使用[Loupe](http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)視覺化工具進行說明。 <br/> 1.首先會執行`console.log("Hi There.")`。  2.瀏覽器偵測到`setTimeout`,於是將它移動到webAPIs做執行,主程式繼續往下執行。  3.執行`console.log("Hello again.")`。  4.五秒過後setTimeout執行完成,移動至Callback Queue 裡等待傳喚  5.Event Loop發現Stack裡任務皆被清空,會呼叫Callback Queue裡面的任務丟進Stack裡,執行`console.log("passed 5 sec.")`。  [點擊這裡可以看在Loupe上執行的效果](http://latentflip.com/loupe/?code=Y29uc29sZS5sb2coIkhpIFRoZXJlLiIpCgpzZXRUaW1lb3V0IChmdW5jdGlvbiBjYWxsYmFjaygpewogICAgY29uc29sZS5sb2coInBhc3NlZCA1IHNlYy4iKQp9LDUwMDApCgpjb25zb2xlLmxvZygiSGVsbG8gYWdhaW4uIik%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) 將流程視覺化後可以顯而易見的了解到,當程序中出現非同步程式時會被隔離到webAPIs執行,就不會擋住主程式,避免掉同步執行時會有的阻塞(block)現象。經過圖像化的說明後,是不是變得比較好理解了呢? ### 關於setTimeout的毫秒數 另外`settimeout`裡面所設定的毫秒數只能代表他==至少==需要多少時間,就像前面所說的,程式執行完成後會進到`Callback queue`等待`EventLoop`偵測當前`Stack`是否為空,才會依序做執行。 假如今天有一段代碼如下:  執行後的結果會是這樣  由此可說明setTimeout只能確保幾毫秒過後程式==即將==會被執行,並不表示幾毫秒過後它會即刻被執行。 [點擊這裡可以看在Loupe上執行的效果](http://latentflip.com/loupe/?code=c2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJzFzZWMgbGF0ZXI%2FJykKfSwgMTAwMCkKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJzFzZWMgbGF0ZXI%2FJykKfSwgMTAwMCkKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJzFzZWMgbGF0ZXI%2FJykKfSwgMTAwMCkKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coJzFzZWMgbGF0ZXI%2FJykKfSwgMTAwMCk%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) ## ### 參考資料 [MDN-webAPIs](https://developer.mozilla.org/zh-TW/docs/Web/API) [Philip Roberts: What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf) [JavaScript、React、Flask、MongoDB 網站全端開發:從入門到進階](https://www.udemy.com/course/javascript-es6-react-redux/)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up