之前知識星球有同學問道了這樣一個問題:Node 環(huán)境和瀏覽器環(huán)境有什么區(qū)別?這樣的思考很值得鼓勵,在對比中學習,很容易將一個抽象的知識具象化。當時的回答只是簡單的畫了個圖,感覺有必要用此文來深入挖掘一下
二、什么是前端,什么是后端?
想必沒有哪個同學不知道,Node 將 Js 擴展到了后端,雖然前端與后端在猿界是高頻詞匯,恐怕也未必能回答清楚什么是前端,什么是后端這個問題?
存在于每個同學的潛意識里的答案:Web 前端指的是用戶看得見摸得著的東西,包括 UI 層面以及 Web 層面的交互實現(xiàn);后端更多的是與數(shù)據(jù)庫進行交互以處理相應(yīng)的,實現(xiàn)功能、數(shù)據(jù)的存取、平臺的穩(wěn)定性以及性能等等
我想說的是一個通信層面上的區(qū)分, Web 應(yīng)用基本上是基于 HTTP/HTTPS 構(gòu)筑的,前端(或者我們延伸到大前端:Android、IOS、瀏覽器等多端)作為 HTTP/HTTPS 的 Client 端,而后端則作為協(xié)議的服務(wù)端
結(jié)合上述兩點,可以簡單的畫一個圖:

通過這個對比來服務(wù)于我們對于 Node 的理解,運行在瀏覽器的 Js 主要是操作 Dom (UI 層面),以及作為 HTTP 客戶端操作網(wǎng)絡(luò)通信。而擴展到服務(wù)器端的 Node,能力不再受瀏覽器沙盒的限制,可以啟動 HTTP 服務(wù)(以及 WebSocket 等各種服務(wù)),可以操作數(shù)據(jù)庫、輕松讀寫磁盤文件,等等等等
三、Node 和瀏覽器的組件構(gòu)成對比

是時候祭出用來回答開篇提到的知識星球問題的圖了,在 Node 橫空出世之前,Js 的主要運行環(huán)境是瀏覽器(Android/IOS 中的 WebView 也是瀏覽器),瀏覽器主要由布局引擎(也就是我們常常說的瀏覽器內(nèi)核)和Javascript 引擎組成,拿 Chrome 瀏覽器來說,它的布局引擎是 WebKit(高版本的已經(jīng)換成 Blink),布局引擎的主要作用就是解析 Html Dom 和 Css 樣式規(guī)則;Javascript 引擎是 V8,顧名思義,Javascript 引擎的作用當然是編譯執(zhí)行 javascript
相比之下,Node 就不需要布局引擎了,畢竟不需要渲染界面,所以在 Node 中是沒有 Window 對象的,因為它木有 Dom、Bom 的 api。注意到圖中左右皆有中間層,但是它們并不一樣,前者基于瀏覽器的沙盒,后者基于 libuv,在 IO 讀寫上的能力是不一樣的,例如:在 Node 上可以輕松的讀寫磁盤文件,但是在瀏覽器中,麻煩到懷疑人生
至于 V8,已經(jīng)超出了我能詳細講解的能力范圍,但是 V8 作為一個開源的 Javascript 引擎,你可以很方便在你的應(yīng)用中調(diào)用,舉個栗子:
#include <v8.h>
using namespace v8;
int main(int argc, char *argv[]) {
// 創(chuàng)建一個句柄作用域 ( 在棧上 )
HandleScope handle_scope;
// 創(chuàng)建一個新的上下文對象
Persistent<Context> context = Context::New();
// 進入上一步創(chuàng)建的上下文,用于編譯執(zhí)行 helloworld
Context::Scope context_scope(context);
// 創(chuàng)建一個字符串對象,值為'Hello, Wrold!', 字符串對象被 JS 引擎
// 求值后,結(jié)果為'Hello, World!'
Handle<String> source = String::New("'Hello' + ', World!'");
// 編譯字符串對象為腳本對象
Handle<Script> script = Script::Compile(source);
// 執(zhí)行腳本,獲取結(jié)果
Handle <Value> result = script->Run();
// 釋放上下文資源
context.Dispose();
// 轉(zhuǎn)換結(jié)果為字符串
String::AsciiValue ascii(result);
printf("%s\n", *ascii);
return 0;
}
可以用一句話來概括上述使用 C++ 編寫的 V8 調(diào)用實例:將 Js 代碼(字符串形式),丟到 V8 中執(zhí)行并返回執(zhí)行結(jié)果。這是最簡單的 V8 調(diào)用模板,要知道,Node 也是使用 C++ 基于 V8 寫出來的,通過這個例子,是否對 Node 有多一點點的認識呢?
四、類比 Java 虛擬機
對 Java 有一定了解的同學,對它的跨平臺特性肯定耳熟能詳,這得益于它的虛擬機,什么是虛擬機?這又可以通過 Node 環(huán)境來幫助理解
Node 剛開始并沒有 Windows 版本,知道 2011 年 7 月,Node 在微軟的幫助下發(fā)布了 Windows 版本,從而實現(xiàn)了跨平臺。兼容 Windows 和 *nix 平臺主要得益于 Node 在操作系統(tǒng)與上層模塊之間構(gòu)建了一層平臺架構(gòu)層,也就是第三節(jié)中的中間層,也即 libuv。libuv 是許多系統(tǒng)實現(xiàn)跨平臺的基礎(chǔ)組件,感興趣可以去了解下(具體的我也說不清楚了~~)
回到什么是虛擬機的問題,莫不過是在系統(tǒng)于上層模塊之間架設(shè)的一套 IO 橋階層
五、總結(jié)
不要給自己的知識領(lǐng)域設(shè)定邊界~~
菲麥前端 是一個讓知識深入原理的知識社群,我們有 知識星球、公眾號以及群,歡迎加微勾搭:facemagic2014