Skip to content

Node 学习

Node.js 中文网:Node.js 中文网 (nodejs.cn)

Node.js 简介

  • 免费、开源、跨平台(Windows、Linux、Mac OS X、etc)
  • 服务器上的JavaScript运行环境
  • 基于Chrome V8引擎,事件驱动、非阻塞式I/O

Node.js 是一个能够在服务器端运行JavaScript的开放源代码、是一个跨平台 JavaScript 运行环境

Node.js 不是一门新的编程语言,也不是一个 JavaScript 框架,它是一套 JavaScript 运行环境,用来支持 JavaScript 代码的执行。

用编程术语来讲,Node.js 是一个 JavaScript 运行时(Runtime)。

JavaScript 诞生于 1995 年,几乎是和互联网同时出现;Node.js 诞生于 2009 年,比 JavaScript 晚了 15 年左右。

node版本兼容查询网站

Node.js 的诞生

谷歌公司在 Chrome 浏览器中集成了一种名为“V8”的 JavaScript 引擎(也即 JavaScript 解释器),它能够非常快速地解析和执行 JavaScript 代码。

V8 引擎官网:https://v8.dev/

V8 引擎使用 C++ 语言编写,可以独立运行,也可以嵌入到任何其它 C++ 程序中。谷歌公司将 V8 引擎甚至整个 Chrome 浏览器都开源了,任何人都可以免费地将 V8 应用到自己的项目中。

Ryan Dahl 和他的团队 基于 V8 引擎开发了独立的 JavaScript 运行时,并命名为 Node.js

为了避免被误认为是 JavaScript 框架,现在也经常简称为 Node。

运行时是什么?

所谓运行时,就是程序在运行期间需要依赖的一系列组件或者工具;把这些工具和组件打包在一起提供给程序员,程序员就能运行自己编写的代码了。

对于 JavaScript 来说,它在运行期间需要依赖以下组件:

1) 解释器

JavaScript 是一种脚本语言,需要一边解释一边运行,用到哪些源代码就编译哪些源代码,整个过程由解释器完成。没有解释器的话,JavaScript 只是一堆纯文本文件,不能被计算机识别。

2) 标准库

我们在 JavaScript 代码中会调用一些内置函数,这些函数不是我们自己编写的,而是标准库自带的。

3) 本地模块

所谓本地模块,就是已经被提前编译好的模块,它们是二进制文件,和可执行文件在内部结构上没有什么区别,只是不能单独运行而已。这些本地模块其实就是动态链接库(在 Windows 下是 .dll 文件),如果你使用过 C 语言、C++ 等编译型语言,那你应该能够更好地理解它。

JavaScript 的很多功能都需要本地模块的支持,比如:

  • Cookie 用于存储少量的用户数据,它是用户计算机上的一种小文件,使用 Cookie 必须有文件操作模块的支持。
  • Ajax 可以借助互联网从服务器请求数据,这是一种网络操作,必须有网络库的支持。
  • 一步一步跟踪代码的执行流程,从中发现逻辑错误,这个过程叫做调试,需要有调试器(Debugger)的支持。
  • JavaScript 可以操作 HTML,这需要 HTML 解析模块提前构建起 DOM 树。

本地模块一般封装了通用功能,对性能要求较高,所以通常使用编译型语言来实现,比如 C 语言、C++、汇编语言等。

JavaScript 解释器需要本地模块的支持,标准库在编写时也会调用本地模块的接口,而我们编写的 JavaScript 代码一般不会直接使用本地模块,所以 Web 前端程序员触及不到它们。

本地模块是幕后英雄,它不显山露水,但是又不可或缺。

总结

解释器、标准库、本地模块等各种组件/工具共同支撑了 JavaScript 代码的运行,它们统称为 JavaScript 运行时。

在 Node.js 之前,JavaScript 运行时被绑定在浏览器中,作为浏览器的各种模块出现。这意味着,要想运行 JavaScript 代码就必须启动浏览器,JavaScript 逃不出浏览器的手掌心,它的功能受到很大的限制,只能作为网页脚本使用。

Node.js 的组成

Node.js 运行时主要由 V8 引擎、标准库和本地模块组成,尤其是本地模块的多少,从底层决定了 Node.js 功能的强弱。

1) V8 引擎

V8 引擎就是 JavaScript 解释器,它负责解析和执行 JavaScript 代码。

V8 引擎借鉴了 Java 虚拟机和 C++ 编译器的众多技术,它将 JavaScript 代码直接编译成原生机器码,并且使用了缓存机制来提高性能,这使得 JavaScript 的运行速度可以媲美二进制程序。

2) 本地模块

Node.js 集成了众多高性能的开源库,它们使用 C/C++ 语言实现,比如:

模块说明
libuv一个跨平台的、基于事件驱动的异步 I/O 库。但是 libuv 不仅限于  I/O,它还提供了进程管理、线程池、信号处理、定时器等其它功能。

Linux 中一切皆文件,这里的 I/O 不仅仅包括文件读写,还包括数据库读写、网络通信(socket)等。
nmpNode.js 包管理器,可以下载包、安装包、卸载包、更新包、上传包等。
http_parser一款由 C 语言编写的轻量级 HTTP 解析器,用以支持 Web 应用开发。
zlib工业级的数据压缩/解压模块,Nodejs 借助 zlib 来创建同步、异步或者流式的压缩/解压接口。
OpenSSL该模块提供了经过严密测试的许多加密/解密功能,现代 Web 依赖这些功能来实现安全性,比如 SSL 协议和 https 协议。
c-ares异步 DNS 查询和解析库。

Node.js 直接在计算机上运行 JavaScript 代码,并且要赋予 JavaScript 强大的能力,所以它的本地模块和浏览器中的运行时有很多大区别,甚至说几乎没有什么关联。Node.js 几乎完全抛弃了浏览器,自己从头构建了一套全新的 JavaScript 运行时。

3) 标准库

本地模块使用 C/C++ 编写,而 Node.js 面向 JavaScript 开发人员,所以必须要封装本地模块的 C/C++ 接口,提供一套优雅的 JavaScript 接口给开发人员,并且要保持接口在不同平台(操作系统)上的一致性。

这套 JavaScript 接口,就是 Node.js 标准库。标准库是否优雅和强大,决定了 Node.js 的易用性,直接影响 Node.js 的市场表现。

总结

V8 引擎和众多本地模块都是现成的,别人已经造好了轮子,Node.js 的主要工作就是选择合适的模块,将它们集成在一起,并编写好 JavaScript 接口。

当然,并不是所有的本地模块都能找到合适的,Node.js 也自己编写了几个模块,典型的代表就是 Libuv。Libuv 是 Node.js 最核心最基础的模块,Node.js 完全基于 Libuv 而构建。

你可能听说过 Node.js 采用了基于事件的、单线程的异步 I/O 架构,这是 Node.js 最大的特点,也是它和其它脚本语言最大的区别,Node.js 的这种能力就是依赖 Libuv 实现的。

Libuv 如此强大,官方决定将它从 Node.js 中剥离出来,作为一个单独的网络库发布,并且开源免费。现在的 Libuv 已经变得非常流行,和传统的  Libevent 和 libev 库并称为“C/C++ 三大网络库”。

Node.js 之所以大名鼎鼎,主要是因为它采用了 V8 引擎和 Libuv 库:V8 引擎保证了 Node.js 运行高效,Libuv 库提供了基于事件循环的异步 I/O 能力。

Libuv 官网:http://libuv.org/

为什么学习 Node?

  • IO 优势
    • 对于文件读写,Node 采用的是非阻塞 IO
    • 传统 IO 在读写文件的时候 CPU 来处理,而代码执行也处于等待中,浪费性能
    • 非阻塞 IO 将读写操作交给 CPU,而代码正常执行,减少等待浪费的性能
  • 应用场景
    • 实际应用: webpack/gulp/npm/http-server/json-server
    • 服务器中负责 IO 读写的中间层服务器(天猫中间层 IO 服务器)

总结

Node.js 是一个 JavaScript 运行时,它让 JavaScript 脱离了浏览器环境,可以直接在计算机上运行,极大地拓展了 JavaScript 用途。我们应该将 JavaScript 和 Python、Java、Ruby 等其它编程语言同等对待,不能再将它视为一种“小玩意”。

最后我们来汇总一下 JavaScript 和 Node.js 的历史:

  • Netscape 浏览器衍生出了 JavaScript 脚本,赋予网页编程能力;
  • Chrome 浏览器衍生了 V8 引擎,提高了 JavaScript 性能;
  • V8 引擎构建了 Node.js,拓展了 JavaScript 的编程能力;
  • Node.js 衍生了 Libuv 库,给网络开发增加了一款优秀的工具。

Released under the MIT License.