Skip to content

Node 基础

Node 是什么

Node 是 JavaScript 的一种运行环境,是一个基于 Chrome V8 引擎建立的一个平台。由于采用了事件驱动、非阻塞 I/O 的模型和单线程处理请求,这使得它非常适合处理大量并发连接、实时应用和数据密集类型的应用程序

  • 后端 Web 服务器开发与网络爬虫开发
  • 脚手架命令行工具
  • 图形界面应用程序开发

Node.js 特点

非阻塞 I/O

单线程

事件驱动

npm 包管理

无缓冲

可扩展

Node.js 发展

  • 2008 V8 引擎随 Chrome 浏览器问世
  • 2009 年 Ryan Dahl,发布了 Node.js 项目

https://webapplog.com/you-dont-know-node/

https://github.com/Walikrence/-/blob/master/TODO/you-dont-know-node.md

(13个基础核心模块)

Node 全局对象

在浏览器中,我们有 documentwindow 等全局对象;而 Node 只包含 ECMAScript 和 V8,不包含 BOM 和 DOM,因此 Node 中不存在 documentwindow;取而代之,Node 专属的全局对象是 process

JavaScript 全局对象的分类

在此之前,我们先看一下 JavaScript 各个运行环境的全局对象的比较,如下图所示:

各个运行环境的全局对象

可以看到 JavaScript 全局对象可以分为四类:

  1. 浏览器专属,例如 windowalert 等等;
  2. Node 专属,例如 process__dirname__filename 等等
  3. 浏览器和 Node 共有,但是实现方式不同,例如 consolesetTimeoutsetInterval
  4. 浏览器和 Node 共有,并且属于 ECMAScript 语言定义的一部分,例如 DateStringpromise

Node 专属全局对象解析

process 进程

process 全局对象可以说是 Node.js 的灵魂,它是管理当前 Node.js 进程状态的对象,提供了与操作系统的简单接口。

有哪些属性
  • pid:进程编号
  • env:系统环境变量
  • argv:命令行执行此脚本时的输入参数
  • platform:当前操作系统的平台

提示

可以在 Node REPL 中尝试一下这些对象。像上面说的那样进入 REPL(你的输出很有可能跟我的不一样):

bash
$ node
Welcome to Node.js v12.10.0.
Type ".help" for more information.
> process.pid
3
> process.platform
'darwin'

Buffer

Buffer 全局对象让 JavaScript 也能够轻松地处理二进数据流,结合 Node 的流接口(Stream),能够实现高效的二进制文件处理

__filename__dirname

分别代表当前所运行 Node 脚本的文件路径和所在目录路径

module 模块

Node 实现了一个简单模块记在系统。在 Node 中,文件和模块是一一对应的关系,可以理解为一个文件就是一个模块。其模块系统的实现主要依赖于全局对象 module,其中实现了 exports(导出)、require(加载)机制

简单来说,commonJS 导出的是值的拷贝,而非值的引用,这与 ES6 中的模块化是不一样的

Node 中的模块机制

之前没有模块化

模块化的历程

简单来说:

IIFE——CommonJS——AMD/CMD——ES6 模块(mjs)

什么是 Node 模块

在正是分析 Node 模块机制之前,我们需要明确定义什么是 Node 模块。通常来说,Node 模块可分为两大类:

  • 核心模块:Node 提供的内置模块,在安装 Node 时已经被编译成二进制可执行文件
  • 文件模块:用户编写的模块,可以是自己写的,也可以使通过 npm 安全的

exports 对象本质上是 module.exports 的引用。也就是说,下面两行代码是等价的

javascript
// 导出 add 函数
exports.add = add;

// 和上面一行代码是一样的
module.exports.add = add;

module 对象

module 在每个模块中表示对当前模块的引用。而 module.exports 又可以通过全局对象 exports 来引用。module 并不是一个全局对象,而更像一个模块内部对象

module.children

这个模块引入的所有模块对象

module.exports

module.exports 通过模块系统创建。

export 与 module.export 的区别

导出多个成员(必须在对象中)

javascript
exports.a = 123;
exports.b = 'hello';
exports.c = function () {
    console.log('ccc');
};
exports.d = {
    foo: 'bar',
};

导出多个成员也可以这样写

javascript
module.exports = {
    foo: 'bar',
    add: function () {
        console.log('aa');
    },
};

导出单个成员(拿到的就是:函数,字符串)

javascript
module.exports = 'hello';

以下情况会覆盖:

javascript
module.exports = 'hello'

// 以这个为准,后者会覆盖前者
module.exports = function(x, y) {
return x + y
}
exportsmodule.exports 的一个引用

console.log(exports === module.exports) // => true

exports.foo = 'bar'

// 等价于
module.exports.foo = 'bar'

事件触发器 Events 模块

Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效

大多数 Node.js 核心 API 都采用惯用的事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器),那么 Node.js 是如何实现事件驱动的

参考资料