世界上誤解最大的語言 JavaScript 之 JS 到底是同步與非同步語言?!
前言
許多網路文章都可以看到許多人都說 JavaScript 是一個非同步語言,但是經過一些事情觀念驗證後才發現,這個誤解可大了,所以這一篇就來講一下 JavaScript 到底是非同步語言還是同步語言。
JavaScript
JavaScript 在一開始主要是用於瀏覽器上運行的程式語言,也因為 JavaScript 不需要消耗伺服器的資源而非常受歡迎,但早期 JavaScript 只能用於瀏覽器使用,直到後來出現 Node.js,才改變了 JavaScript 這個語言。
首先我們在網路上 Google 都會發現人家說 JavaScript 是一個非同步單執行緒語言。
首先先講單執行緒,單執行緒的簡單講就是一次只能執行一個動作,這個算好理解。
那非同步呢?首先同步的意思簡單來講就是「按部就班」的概念,它是一行一行的執行,而非同步則是它不是一行一行執行有可能會跳行執行,所以試著思考一下以下這個範例。
1 | setTimeout(() => { |
上面這個經典範例中,許多文章都是用這個範例來介紹 JavaScript 是一個非同步語言,因為優先出現的是 b 而非 a,但是事實上真的代表 JavaScript 是非同步語言嗎?並不是,Why?
JavaScript 在執行的時候並沒有忽略 setTimeout()
這一行語法,而是將 setTimeout
放置在 JavaScript 的一個特性中,也就是所謂的事件佇列 (event quete)。
而事件佇列在卡斯柏老師文章中有非常詳細的 範例說明。
JavaScript 在執行的時候是依照同步的概念去執行的,當遇到需要非同步的事件,例如:setTimeout
此時 JavaScript 就會將它丟進事件佇列中,並執行下一行。
JavaScript 是一個同步語言
其實我們也可以從一些文章抽絲剝解翻到 JavaScript 是一個同步語言,例如我先前寫的 [JS奇怪的世界]No.6 執行環境:程式執行 就有提到「創造完變數後才會開始執行一行一行執行並賦與值」。
此外還有 stackoverflow 中的其中一篇文章 When is JavaScript synchronous? 底下也有許多人提到
- JavaScript is always synchronous and single-threaded. (JavaScript 一直都是同步語言且是單執行緒。)
- JavaScript is single threaded and has a synchronous execution model (JavaScript 是一個單執行緒並且具有同步執行特性的語言)
- JavaScript is single-threaded, and all the time you work on a normal synchronous code-flow execution. (JavaScript 是一個單執行緒並且會依照程式碼同步執行)
那為什麼那麼多人會誤以為 JavaScript 是一個非同步語言呢?主要原因就是 JavaScript 的事件佇列這個特性導致。
最後 Medium 上也有一篇文章提到 JavaScript 是一個同步語言 → Is JavaScript Synchronous or Asynchronous? What the Hell is a Promise?
- JavaScript is Synchronous (JavaScript 是同步語言)
在這一篇 Medium 底下有這幾張圖我覺得相當不錯,在一開始 JavaScript 是先執行過一次程式碼
後來再將需要做非同步的事件丟進事件佇列中
我們可以看到 JavaScript 一開始是會將所有程式碼執行一遍,並將需要做非同步事件的程式碼(function)丟進事件佇列中。
所以我們也可以試著還原看看圖片中的程式碼
1 | function A() { |
文章也有提到,若不希望發生事件佇列這種狀況,那麼就可以使用 Promise、Asnyc、Await 的來避免,這邊就不再多做範例,若對 Promise、Asnyc、Await 好奇可以參考這三篇文章