最近在SegmentFault解題,一個問題比較讓我比較印象深入:一個初學者試圖在瀏覽器中導入Node.js的net模塊。結果在控制檯打印後是一個空對象。javascript
對於有點Javascript經驗的人來講,這是一個‘弱智’問題,怎麼能夠在瀏覽器端運行Node程序呢?由於這些Node模塊通過Webpack處理, 因此變成了一個空對象,更好的處理方式應該是拋出異常.html
仔細反思一下,對於這些剛入門Javascript的或者從其餘語言切換過來的開發者,他們壓根就沒有概念,好比Python、Ruby、Java這些語言都有強大的標準庫,能夠知足80%的開發需求,無論它在什麼環境、什麼平臺運行,基本上均可以統一使用這套標準庫。而Javascript目前的現狀是:不一樣的運行環境,API結構是割裂的。java
Javascript這門十幾天開發出來的、專供瀏覽器的語言,可能當初設計是根本就沒有考慮標準庫這些玩意,好比文件系統,網絡等等。由於這個背景, Javascript長期不具有獨立性,它深度依賴於瀏覽器這個運行環境, 處於一種給瀏覽器打輔助的角色, 因此Javascript不少年沒有走出瀏覽器玩具語言這個範圍.node
固然這既是劣勢,也是優點, 如今沒任何語言能撼動Javascript在瀏覽器中的地位。python
我想不少人跟我當初同樣認爲瀏覽器提供的Web API === Javascript的標準庫, 好比console.log
、setTimeout
(下文會介紹這些功能都不在Javascript規範裏面). 正如當年那些把JQuery當成‘Javascript’的人.webpack
直到NodeJS的出現,Javascript才掙脫瀏覽器約束,延伸到服務器領域, 再也不是一個'沙盒語言'。NodeJS定義了不少模塊來支撐服務端的開發, 如fs、os、Buffer、net。可是這些API同樣不是Javascript的標準、也就是說NodeJS !== Javascript.git
再到後來,學不動了,NodeJS原做者吐槽了一通NodeJS,又搞出了一個Deno, 它也會有本身標準庫,會定義本身的文件系統、網絡API。從名字上就暗示着這些API不可能和NodeJS兼容。Ok,如今回到文章開始那個問題,若是deno發展起來,說不定哪天又有人嘗試在瀏覽器引用Deno的模塊?github
如上圖, Javascript實際上是有一層比較薄全局的、通用的、標準的、核心的API層,即標準內置對象
,這是一些語言核心的內置對象,能夠全局訪問。關鍵的是這些是標準的,它們在ECMAScript規範中被定義. 在這個基礎之上,不一樣的運行環境拓展了本身的API。golang
以瀏覽器爲例:web
瀏覽器端的Web API是一個很是複雜API集合,上圖總結了一下,基本就包含兩塊東西:
WebAPI基本概覽:
若是你有留心查看MDN文檔下面的規範引用,你會發現有些規範引用了W3C, 有些則引用了WHATWG. 到底誰說了算?
若是你掀開鍋蓋,就會發現這是一場鬧劇. 若是前陣子有關注新聞,會看到這些標題‘WHATWG 擊敗 W3C,贏得 HTML 和 DOM 的控制權’、'W3C將與WHATWG合做制定最新HTML和DOM規範標準'. 大概能夠猜出這兩個組織之間的關係. 本文就不扯這些‘八卦’了,相關背景能夠看這篇文章WHATWG 擊敗 W3C,贏得 HTML 和 DOM 的控制權
相對而言, 語言層則由ECMAScript規範定義的,比較獨立, 近些年成果也比較顯著.
這些全局基本對象數量不多, 這些對象是每一個JavaScript開發者必須掌握的.
平時咱們使用的很是頻繁的Timer和Console都再也不此列.
這些對象只能知足很基本開發需求, 根本不能和其餘語言的標準庫相比. 固然這和語言的定位也有必定關係
標準庫沒有一個嚴格的定義,按照Wiki的說法標準庫就是該語言在不一樣實現中都按例提供的庫, 好比Ruby官方實現cRuby和基於JVM的JRuby都按照官方標準庫規範實現了標準庫。 標準庫怎麼設計,須要包含什麼內容取決於語言各自秉持的哲學和定位。 我認爲標準庫應該有如下特徵:
至於標準庫須要包含什麼內容,能夠參考其餘語言的實現。好比:
大概分析一下,它們標準庫大體都有這些內容:
大部分語言的核心都很小(C++除外),咱們學一門語言,大部分時間是花在標準庫上和語言的生態上面,可是你會發現這些標準庫通常都是大同小異,這就是爲何有經驗的開發者能夠很快地入手一門語言.
顯然上面這些功能大部分在NodeJS中已經實現了,鑑於NodeJS這麼普遍的使用率,NodeJS能夠算是事實上的標準了
顯然要結合當前的背景來辯證地考慮。
有標準庫有什麼好處?
標準庫可能會有什麼問題?
如何設計標準庫? 標準庫推動進程可能會有什麼障礙?
NodeJS已是事實上的標準, 怎麼兼容現有的生態?
標準庫應該包含什麼內容,如何保持和社區同步?
如何把控標準庫內容的尺度?
最小化的標準庫容易被維護和升級,但可能出現'沒什麼卵用'的狀況;
最大化的標準庫,例如Java的標準庫,幾乎包含了全部的東西,開發者能夠快速開發一個東西, 可是過了幾年不少API就會變得過期,通常爲了保持向下兼容,這些API會一直像一根刺同樣卡在那裏. 另外一個很是典型的反例就是PHP的標準庫,這裏能夠看到各類風格的API.
標準庫是跟隨語言發佈的,若是你的項目中使用了過期的API,又想升級語言版本,就須要重構項目。而使用第三方庫則可能能夠保持不動。
Javascript的主要戰場仍是瀏覽器, 標準庫是否應該有一個'基本版'(用於瀏覽器或者一些抽象操做系統的運行環境), 還有個'旗艦版'(服務端), 或者只提供一個跨越全部平臺的標準庫?
如何處理兼容性問題? 老舊瀏覽器如何Polyfill?
如何與現有的全局對象或用戶模塊分離?
proposal-javascript-standard-library 這是一個很是早期的語言提議,定義瞭如何引用標準庫(built-in modules),可是沒有定義標準庫的內容
KV Storage: the Web's First Built-in Module Chrome在年初推出的實驗性功能,嘗試實現proposal-javascript-standard-library提議. 它經過下面方式來引用‘標準庫’模塊:
import {storage, StorageArea} from 'std:kv-storage'; // std: 前綴,和普通模塊區分開來
複製代碼
本文從一個SegmentFault上的一個問題開始,對比其餘語言,揭露Javascript沒有標準庫的窘境. 接着介紹現有Javascript的API結構,介紹什麼是標準庫,辯證考慮標準庫的優缺點,以及推行上面可能會遇到的阻礙.