在对比中理解 Node

2,232 阅读4分钟

之前知识星球有同学问道了这样一个问题:Node 环境和浏览器环境有什么区别?这样的思考很值得鼓励,在对比中学习,很容易将一个抽象的知识具象化。当时的回答只是简单的画了个图,感觉有必要用此文来深入挖掘一下

二、什么是前端,什么是后端?

想必没有哪个同学不知道,Node 将 Js 扩展到了后端,虽然前端与后端在猿界是高频词汇,恐怕也未必能回答清楚什么是前端,什么是后端这个问题?

存在于每个同学的潜意识里的答案:Web 前端指的是用户看得见摸得着的东西,包括 UI 层面以及 Web 层面的交互实现;后端更多的是与数据库进行交互以处理相应的,实现功能、数据的存取、平台的稳定性以及性能等等

我想说的是一个通信层面上的区分, Web 应用基本上是基于 HTTP/HTTPS 构筑的,前端(或者我们延伸到大前端:Android、IOS、浏览器等多端)作为 HTTP/HTTPS 的 Client 端,而后端则作为协议的服务端

结合上述两点,可以简单的画一个图:

有可能要被吐槽的图
有可能要被吐槽的图

通过这个对比来服务于我们对于 Node 的理解,运行在浏览器的 Js 主要是操作 Dom (UI 层面),以及作为 HTTP 客户端操作网络通信。而扩展到服务器端的 Node,能力不再受浏览器沙盒的限制,可以启动 HTTP 服务(以及 WebSocket 等各种服务),可以操作数据库、轻松读写磁盘文件,等等等等

三、Node 和浏览器的组件构成对比

抄袭自 Node 深入浅出的图
抄袭自 Node 深入浅出的图

是时候祭出用来回答开篇提到的知识星球问题的图了,在 Node 横空出世之前,Js 的主要运行环境是浏览器(Android/IOS 中的 WebView 也是浏览器),浏览器主要由布局引擎(也就是我们常常说的浏览器内核)和Javascript 引擎组成,拿 Chrome 浏览器来说,它的布局引擎是 WebKit(高版本的已经换成 Blink),布局引擎的主要作用就是解析 Html Dom 和 Css 样式规则;Javascript 引擎是 V8,顾名思义,Javascript 引擎的作用当然是编译执行 javascript

相比之下,Node 就不需要布局引擎了,毕竟不需要渲染界面,所以在 Node 中是没有 Window 对象的,因为它木有 Dom、Bom 的 api。注意到图中左右皆有中间层,但是它们并不一样,前者基于浏览器的沙盒,后者基于 libuv,在 IO 读写上的能力是不一样的,例如:在 Node 上可以轻松的读写磁盘文件,但是在浏览器中,麻烦到怀疑人生

至于 V8,已经超出了我能详细讲解的能力范围,但是 V8 作为一个开源的 Javascript 引擎,你可以很方便在你的应用中调用,举个栗子:

#include <v8.h> 
using namespace v8; 
int main(int argc, char *argv[]) { 
    // 创建一个句柄作用域 ( 在栈上 ) 
    HandleScope handle_scope; 
    // 创建一个新的上下文对象
    Persistent<Context> context = Context::New(); 
    // 进入上一步创建的上下文,用于编译执行 helloworld 
    Context::Scope context_scope(context); 
    // 创建一个字符串对象,值为'Hello, Wrold!', 字符串对象被 JS 引擎
    // 求值后,结果为'Hello, World!'
    Handle<String> source = String::New("'Hello' + ', World!'"); 
    // 编译字符串对象为脚本对象
    Handle<Script> script = Script::Compile(source); 
    // 执行脚本,获取结果
    Handle <Value> result = script->Run(); 
    // 释放上下文资源
    context.Dispose(); 

    // 转换结果为字符串
    String::AsciiValue ascii(result); 

    printf("%s\n", *ascii); 

    return 0; 
}

可以用一句话来概括上述使用 C++ 编写的 V8 调用实例:将 Js 代码(字符串形式),丢到 V8 中执行并返回执行结果。这是最简单的 V8 调用模板,要知道,Node 也是使用 C++ 基于 V8 写出来的,通过这个例子,是否对 Node 有多一点点的认识呢?

四、类比 Java 虚拟机

对 Java 有一定了解的同学,对它的跨平台特性肯定耳熟能详,这得益于它的虚拟机,什么是虚拟机?这又可以通过 Node 环境来帮助理解

Node 刚开始并没有 Windows 版本,知道 2011 年 7 月,Node 在微软的帮助下发布了 Windows 版本,从而实现了跨平台。兼容 Windows 和 *nix 平台主要得益于 Node 在操作系统与上层模块之间构建了一层平台架构层,也就是第三节中的中间层,也即 libuv。libuv 是许多系统实现跨平台的基础组件,感兴趣可以去了解下(具体的我也说不清楚了~~)

回到什么是虚拟机的问题,莫不过是在系统于上层模块之间架设的一套 IO 桥阶层

五、总结

不要给自己的知识领域设定边界~~

菲麦前端 是一个让知识深入原理的知识社群,我们有 知识星球、公众号以及群,欢迎加微勾搭:facemagic2014