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版本兼容查询网站
nvm: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)等。 |
nmp | Node.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 库,给网络开发增加了一款优秀的工具。