首先要糾正一個誤區(qū):JS其實就是一門語言猜揪,說是單線程還是多線程得結(jié)合具體運行環(huán)境(瀏覽器)。
瀏覽器的內(nèi)核是多線程的贱枣。
一個瀏覽器通常由以下幾個常駐的線程:
渲染引擎線程:顧名思義月洛,該線程負責頁面的渲染
JS引擎線程:負責JS的解析和執(zhí)行
定時觸發(fā)器線程:處理定時事件,比如setTimeout, setInterval
事件觸發(fā)線程:處理DOM事件
異步http請求線程:處理http請求
JS引擎
負責JS代碼的解析和執(zhí)行(注意是瀏覽器自己開了一個線程)漠嵌。通常包括以下幾個步驟:
詞法分析:將源代碼分解為有意義的分詞
語法分析:用語法分析器將分詞解析成語法樹
代碼生成:生成可執(zhí)行代碼(將所有JS代碼全部生成為可執(zhí)行代碼)
函數(shù)調(diào)用棧的更新:遵循代碼順序,不同上下文出入函數(shù)調(diào)用棧盖呼。伴隨函數(shù)調(diào)用棧的更新儒鹿,JS代碼逐句執(zhí)行至尾部。
瀏覽器在運行時只開啟了一個JS引擎線程來解析和執(zhí)行JS几晤。且要記得無論是同步還是異步執(zhí)行约炎,JS引擎線程的運行始終是非阻塞的,這是在設計之初就定下的蟹瘾。
JS異步執(zhí)行
JS引擎的事件循環(huán)機制是JS實現(xiàn)異步執(zhí)行的前提圾浅。在上下文的不斷切換,函數(shù)調(diào)用棧的更新過程中憾朴,一旦發(fā)現(xiàn)"事件綁定狸捕,AJAX,setTimeout/setInterval"等任務众雷,會把它們會將其放入消息隊列中灸拍。當函數(shù)調(diào)用棧為空時,JS引擎會執(zhí)行一次循環(huán)砾省,將事件隊列的隊首出隊至函數(shù)調(diào)用棧中鸡岗。
待續(xù)