# CommonJS 的模块规范

  • 内容
    • 模块
    • 二进制
    • buffer
    • 字节集编码
    • I/O流
    • 进程环境
    • 文件系统
    • 套接字
    • 单元测试
    • web服务器网关接口
    • 包管理

# 1.模块的定义

  • 上下文提供require()方法来引入外部模块
  • 对应功能,上下文提供exports对象用于导出当前模块的方法或变量,也是唯一出口
  • 模块中存在module对象, 代表模块本身
  • exportsmodule属性
  • module.exports
  • exports
  // math.js
  exports.add = function() {
    var sum = 0,
      i = 0,
      args = arguments,
      l = args.length;

    while(i < l) {
      sum += args[i++];
    }
    return sum;
  }

# 2.模块的使用

# require()

  • 符合小舵峰命名
  • 可以没有文件后缀名
// program.js
var math = require('math')
var val = math.add(12, 23, 43)
console.log(val)

# 3.node 的模块实现

  • 引入,经历三个步骤
    • 路径分析
    • 文件定位
    • 编译执行

# 核心模块和文件模块

# 优先从缓存加载

  • 核心模块
    • 在node源代码编译过程中,编译进了二进制文件
    • node启动时,直接加载进内存中
    • 核心模块使用时省略 文件定位 编译执行
  • 文件模块
    • 运行时动态加载

# 路径分析

# 模块标识符分析

  • 核心模块 --> 名称查找
  • 自定义模块 --> 路径分析查找

# 文件定位

  • 文件扩展名
    • 查找优先级 .js > .json > .node (一般不是js后缀 要加上)
  • 目录分析和包
    • 如果是一个目录 当作包来处理
    • node在当前的目录下查找 package.json
    • 通过 JSON.parse()解析包描述对象
    • 得到 main属性指定的文件名进行定位
    • 默认文件名 index.js > index.json > index.node

# 编译执行

  • 文件模块都是一个对像
  • 定位到具体的文件后, Node会新建一个模块对象,然后根据路径载入并编译
function Module(id, parent) {
  this.id = id;
  this.exports = {};
  this.parent = parent;
  if (parent && parent.children) {
    parent.children.push(this);
  }

  this.filename = null;
  this.loaded = false;
  this.children = [];
}
  • 不同的文件扩展名,载入的方式也不同
    • .js文件。 通过fs模块同步读取文件后编译
    • .node文件。 用 C/C++编写的扩展文件,通过dlopen()方法加载后编译生成的文件
    • .json文件。 通过fs模块同步读取文件后, 用JSON.parse()解析返回结果
    • 其他当作.js

# 核心模块

  • 两部分
    • C/C++编写 存放在 Node项目的src目录下
    • JavaScript编写 存放在 Node项目的lib目录下

# 内建模块导出

  • 文件模块 <---- 核心模块(JavaScript) <----- 内建模块(C/C++)
  • Node 在启动的时候,会生成一个全局变量 process, 并提供 Binding()方法协助加载内建模块

# 核心模块的引入流程

  5. require('os')

  4. NativeModule.require('os')

  3. process.binding('os')

  2. get_builtin_module('node_os')

  1. NODE_MODULE(node_os, reg_func)
上次更新时间: 2019-12-24 2:17:04 PM