最近在閱讀《你不知道的JavaScript中卷》,當(dāng)我看到第二部分介紹異步和回調(diào)函數(shù)的一些知識(shí)時(shí),由于該書在第二部分1、2章對(duì)線程、事件循環(huán)的概念介紹的并非詳細(xì),因此引發(fā)了我的一系列思考。于是寫下這篇小文章,記錄自己對(duì)該知識(shí)點(diǎn)的學(xué)習(xí)和思考。

什么是線程

由于JavaScript是單線程語言,因此,在一個(gè)進(jìn)程上,只能運(yùn)行一個(gè)線程,而不能多個(gè)線程同時(shí)運(yùn)行。也就是說JavaScript不允許多個(gè)線程共享內(nèi)存空間。因此,如果有多個(gè)線程想同時(shí)運(yùn)行,則需采取排隊(duì)的方式,即只有當(dāng)前一個(gè)線程執(zhí)行完畢,后一個(gè)線程才開始執(zhí)行。JavaScript中的線程包括函數(shù)調(diào)用、I/O設(shè)備(如向服務(wù)器發(fā)送請(qǐng)求獲取響應(yīng)等)、定時(shí)器、用戶操作的事件(click、keyup、scroll等)。

由于每個(gè)線程需要排隊(duì)執(zhí)行,因此涉及堆(Heap)、棧(Stack)、隊(duì)列(Queue)的概念。

Heap、Stack、Queue

在MDN上的一篇文章《并發(fā)模型與Event Loop》,介紹了關(guān)于這三個(gè)概念

堆(Heap):對(duì)象被分配在一個(gè)堆中,一個(gè)用以表示一個(gè)內(nèi)存中未被組織的區(qū)域。我們知道,函數(shù)是第一等對(duì)象,同時(shí)函數(shù)是“可調(diào)用的對(duì)象”。因此,當(dāng)函數(shù)在被調(diào)用之前,JavaScript引擎會(huì)對(duì)函數(shù)進(jìn)行編