為什么 JavaScript 到 2025 年還是單線程?
沒錯——手機 12 核、冰箱跑 Linux 的今天,JavaScript 依舊像 1995 年那樣一件事接一件事地做。 最離譜的是?它還挺好用。
可這是怎么做到的?
JavaScript 是“10 天速成”的(真的)
1995 年,Brendan Eich 用十天造出了 JavaScript——比你刷完一部劇的時間還短。
它的最初使命只有一個:
“讓網(wǎng)頁稍微有點交互。點個按鈕?彈個 alert。就這樣?!?/span>
為了簡單且安全,它被設(shè)計為單線程:
- 沒有線程
- 沒有鎖
- 沒有死鎖
- 沒有讓人抓狂的競態(tài)
一次只干一活、一個全局線程、一條巨大的待辦隊列。 這套哲學(xué),直到今天也沒根本改變。
“單線程”到底指什么?
JavaScript 只有一個調(diào)用棧:同一時刻只執(zhí)行一段代碼,A 沒跑完,B 不會上來。 看一段小例子:
console.log("One");
setTimeout(() => console.log("Two"), 1000);
console.log("Three");輸出順序是:
One
Three
Two原因很簡單:setTimeout不阻塞主線程。它的意思大概是:
“嗨瀏覽器,一秒后幫我回調(diào)一下行嗎?”
主線程點點頭,繼續(xù)往下跑。
撐起這一切的,是傳說中的——事件循環(huán)(Event Loop)。
事件循環(huán):JS 的“魔法醬汁”
把它想象成這樣:
- 調(diào)用棧(Call Stack):函數(shù)在這兒真正執(zhí)行;
- 任務(wù)隊列(Task/Callback Queue):回調(diào)、事件在這兒排隊等候;
- 事件循環(huán)(Event Loop):像門口保安一樣重復(fù)檢查—— “??樟藛幔靠樟司?/span>請下一位?!?/span>
需要強調(diào)的是:JS 本體是單線程,但瀏覽器/Node.js會在幕后多線程地代勞:
- 網(wǎng)絡(luò)請求 → 在后臺線程處理;
- 文件讀寫 → 背景完成再回調(diào);
- 定時器、DOM 事件、數(shù)據(jù)庫訪問 → 先異步完成,后入隊等待主線程空閑。
JS 自己不并發(fā)——它會把活外包。
“都 2025 了,為啥不把 JS 直接做成多線程?”
聽上去理所當(dāng)然,對吧?CPU 有 32 線程,JS 也該上吧。然而,真相是:
整個 Web 的設(shè)計默認 JavaScript 是單線程。 DOM、CSSOM、事件系統(tǒng)、各種瀏覽器 API——都假設(shè)同一時刻只有一個“家伙”在動它們。 如果 JS 突然能多線程同時改 DOM,你最愛的站點會像熱鍋上的黃油一樣糊成一攤。
但還有個東西叫 Web Workers,不是嗎?
沒錯,它們很香。Web Workers 允許你開真正的后臺線程并行跑 JS。可也有代價:
- ?? 不能操作 DOM;
- ?? 通過
postMessage()通訊; - ?? 數(shù)據(jù)需要序列化/反序列化。
因此它們適合:
- 重計算(數(shù)值、圖像、視頻處理);
- AI 推理(比如 TensorFlow.js);
但你若在 Worker 里想 document.querySelector('div') 并改它?不行。DOM 歸主線程管。
服務(wù)器端的“多線程”:Node.js 的 Worker Threads
Node 也曾以單線程聞名。如今(Node 12+ 起),Worker Threads 讓它更能打:
- 為 CPU 密集任務(wù)開多個工作線程;
- 用 SharedArrayBuffer 進行內(nèi)存共享;
- 依舊 事件驅(qū)動,但更強壯。
2025 年,高性能 Node 應(yīng)用通常把 異步 I/O 和 Workers 搭著用,既靈活又狠快。
async/await:把“隊列戲法”偽裝成“多線程”
JS 史上最出神入化的把戲,也許就是這對黃金搭檔。async/await 看起來像同步:
async function fetchData() {
const res = await fetch("https://api.whatever.com");
const data = await res.json();
console.log(data);
}它像同步、行徑卻是異步——背后靠 Promise + 事件循環(huán) 調(diào)度。沒線程參與。純粹的錯覺,Copperfield 都會點個贊。
框架陣營如何應(yīng)對?(React / Vue 等)
即便是現(xiàn)代框架,也默認遵守單線程模型。
這就是為什么 React 18 引入了并發(fā)特性(Concurrent Features):通過調(diào)度讓渲染更聰明,而不是去開十個線程。
React 的渲染可以暫停 / 推遲 / 取消,以避免卡住主線程、提升交互流暢度。線程只有一個,體驗卻能更絲滑。
單線程 = 更安全的默認
樸素的模型,帶來可貴的“無聊”:
- 無共享內(nèi)存引發(fā)的詭異 Bug;
- 無死鎖;
- 無互斥鎖地獄;
- 更低的心智負擔(dān)。
Web 的基石要的是可預(yù)期。你可不希望網(wǎng)銀因為兩個線程“搶一個 div”而抽風(fēng)。
接下來會怎樣?JS 會邁向“多線程常態(tài)”嗎?
也許吧,但不會很快。 相關(guān)方向已經(jīng)有:
- Atomics / SharedArrayBuffer(更底層的并發(fā)原語);
- WebAssembly with Threads(WASM 線程化);
- 更靈活的 Workers / 調(diào)度模型。
盡管如此,離“隨手就多線程的 JS”仍有不短的距離。 可能這也沒什么不妥——這門“30 歲的單線程語言”,仍然扛著幾乎整個 Web,而且不打算退場。
JavaScript 并不“笨”——它是“老而聰明”
下回有人吐槽“單線程太拉了”,你可以這樣回他:
“不,它只是把并發(fā)隱藏在舞臺后。靠事件循環(huán)與一堆 Workers,它把混亂編排得井井有條。 它只是不允許你從十個線程同時戳 DOM,然后還自稱聰明?!?/span>
這就是 JavaScript 的美學(xué):單線程,卻從不無聊。





























