JAVAScript(簡稱js)廣泛應用在web開發領域,幾乎是web開發的唯一編程語言,近些年,借助node.js的快速發展,js在服務器領域也有了非常廣泛運用與拓展。
然而,雖然js在前后端都有了一定的發展,很多js開發者也熟練使用大量的js代碼庫,但很多人依然理不清js的各種關鍵術語。
本文不講解具體開發技巧技術,只講解其中的知識點,幫助大家理解這些關鍵術語的內涵。
ECMAScript
js前端面試,總繞不開的一個ES,所以這個ES到底是什么?
從名詞解釋上
ECMAScript是一種由Ecma國際通過ECMA-262標準化的腳本程序設計語言。
說是語言定義,ES更像是一套標準。而我們說的js則是ES的一個實現。歷史上有其他語言實現過ES標準,比如運行在flash上面的actionscript。
ES 并不等于js。
ES涵蓋了js幾乎所有語法層面的東西,記住語法這一點,舉幾個例子
- 寫js幾乎都知道setTimeout/setInterval 這2個計時器函數,然而,ES標準里面至今也沒有對這2個函數的定義說明。 這兩貨壓根就不被正統ES認可。
- 一說到js網絡請求,很多開發人員張口就來XHR和fetch,但是ES標準根本沒有網絡和http的任何定義。
那明明不是ES標準,為何所有瀏覽器都實現了?
這就要牽扯到另一個標準委員會 —— W3C標準委員會。
至于node.js,為了保證絕大多數js庫在不修改的情況下移植到node環境(吸納js開發者),所以也內部實現了這兩個計時器函數,但是網絡庫則是靠另一套模塊來實現。
- 基于上個問題的延伸,ES6以后,JS開發者可能都思考過或者被問過JS的事件循環機制是什么?
事件循環
js事件循環是基于js單線程體系下的最優設計(具體js事件循環原理以后我在單獨講解)。
ES6之前,js事件循環非常單調,除了異步IO、網絡和計時器幾乎沒什么可以講的。ES6以后,事件循環里面有了2個概念:微任務隊列(MicrotaskQueue)和宏任務隊列(macroTaskQueue),如Promise的底層實現就離不開微任務隊列。ES標準想納入Promise協程,就必須把微任務隊列添加到標準里面。
我們也知道setTimeout/setInterval是跟宏任務隊列關聯。但是請切記,宏任務這個也不是ES的標準。
所有的js引擎都沒有提供宏任務隊列的任何API接口,如v8(Chrome和node.js背后的js引擎)、JSC(Safari瀏覽器js引擎)、SpiderMonkey等,你不可能在其中找到宏任務實現接口,宏任務隊列完全由引擎上層依據設計去制定。
比如在Chrome瀏覽器上,一次事件循環里面必須提供供渲染調度的接口,但在node.js里面,無需提供渲染。
事實上,瀏覽器和node.js對宏任務的實現原理有很大差異,node.js靠libuv庫去驅動事件循環。
所以有人有疑問,既然不是標準,那為什么所有瀏覽器和node的js執行環境都提供了宏任務隊列?
這就回到上面的第一句:js事件循環是基于js單線程體系下的最優設計。宏任務隊列是各家巨頭們約定俗成的不成文標準,既不屬于ES也不屬于W3C。
W3C
嚴格意義上說,w3c并不定義或者規范JS標準,它只負責制定web規范并要求各家瀏覽器實現,如html5標準。
W3C討論的標準必須在js的基礎上才能制定。
如網絡請求fetch API,fetch返回Promise,這個就必須在ES6標準之后才能使用。
所以,我們可以這么說,ES則是一種標準沒法直接用,JS是基于ES標準實現的一種編程語言可以用但是需要宿主環境,而W3C標準則負責制定web標準規范,這個標準規范實現依賴js。這三者逐層具象。