简单模拟node.js中require的加载机制

在Node.js中,常用的模块系统是CommonJS规范,其中require函数是加载模块的入口。这里简要介绍一下Node.js中require的加载机制。

加载机制

Node.js中require函数的加载机制基于以下两个原则:
1. 模块只会被加载一次,重复的调用require只会返回内存缓存中已有的模块。
2. 模块的加载顺序是深度优先,同级模块会被加载一次,遇到已加载的模块会停止继续加载。

下面是一个常见的示例:

// a.js
console.log('a start');
require('./b');
console.log('a end');

// b.js
console.log('b start');
require('./c');
console.log('b end');

// c.js
console.log('c start');
console.log('c end');

运行node a.js,会输出以下结果:

a start
b start
c start
c end
b end
a end

上述代码中,a.js调用了require('./b'),Node.js按照深度优先的原则,会首先加载b.jsb.js调用了require('./c'),由于此时c.js还没有被加载过,Node.js又会开始加载c.jsb.js会等待c.js的加载完成,再执行console.log('b end')a.js同理。在整个加载过程中,c.js只被加载了一次,不论有多少模块调用了它。

示例说明

示例一

下面看一下带有exports和module.exports的模块的加载过程。

// moduleA.js
exports.a = 1;
module.exports.b = 2;
console.log('moduleA.js', module.exports);
console.log('exports === module.exports:', exports === module.exports);

// moduleB.js
const moduleA = require('./moduleA');
console.log('moduleA', moduleA);

运行node moduleB.js,输出以下结果:

moduleA.js { a: 1, b: 2 }
exports === module.exports: true
moduleA { a: 1, b: 2 }

moduleA.js中,既通过exports暴露了a属性,也通过module.exports暴露了b属性,这里注意到exportsmodule.exports只是同一个对象的不同引用,引用相同的原因是后续释放只需清空一个对象即可,避免申请额外的内存和减少 V8 引擎的垃圾回收。可见通过exports和module.exports暴露的内容是合并到一个exports中的。
moduleB.js中,只需要加载moduleA.js一次,因此会输出moduleA.js { a: 1, b: 2 }module.exports作为require函数加载的返回值,此处使用moduleA接受。

示例二

模块间相互依赖

//fileA.js
var fileB = require('./fileB.js');
console.log('fileA: ', fileB.content);// undefined

//fileB.js
var fileA = require('./fileA.js');

exports.content= "Hello World";
console.log('fileB: ', fileA);// {}

//main.js
var fileA = require('./fileA.js');
console.log('main: ', fileA); // {test: 123}

运行node main.js,输出以下结果:

fileB:  {}
fileA:  undefined
main:  { content: 'Hello World' }

main.js -> fileA.js -> fileB.js的加载顺序是深度优先,谁先执行完就先返回给调用方。在fileB.jsrequire('./fileA.js')会在fileA.js执行中输出一个空对象,因为此时fileA还没有完全加载并返回,所以fileB.js中的fileA还是空对象。
在这个示例中,因为模块出现循环依赖的情况,所以在fileA.js中访问fileB中的属性时,输出结果是undefined。但是,如果是通过exports暴露接口,而非在模块对象上动态添加接口,这种问题是不会存在的。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:简单模拟node.js中require的加载机制 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • Egg.js 中 AJax 上传文件获取参数的方法

    Egg.js 作为一个基于 Node.js 的企业级开发框架,提供了很多便捷的 API 和插件。在实际开发中,我们很多时候需要使用上传文件的功能。本文将介绍在 Egg.js 中通过 AJAX 方式上传文件并获取参数的方法。 上传文件 在 Egg.js 中通过 AJAX 方式上传文件,可以使用 formidable 插件来解析文件。安装该插件只需要在终端执行一…

    node js 2023年6月8日
    00
  • nodejs express路由匹配控制及Router模块化使用详解

    针对“nodejs express路由匹配控制及Router模块化使用详解”的完整攻略,我会分为以下几个方面进行详细说明: 路由匹配控制 Router模块化使用 示例说明 1. 路由匹配控制 在Node.js的Express框架中,路由控制是指将请求映射到指定的路由处理函数(controller)上。 主要通过app对象的路由apr()方法将处理方法与路由匹…

    node js 2023年6月8日
    00
  • 使用node-canvas在服务端渲染echarts图表解析

    使用node-canvas在服务端渲染echarts图表,可以实现在后端生成静态图表,并且可以在不需要浏览器环境的情况下使用echarts。 安装node-canvas模块 要使用node-canvas在服务端渲染echarts图表,需要预先安装node-canvas模块,命令如下: npm install canvas 注意,node-canvas依赖于C…

    node js 2023年6月8日
    00
  • node.JS的crypto加密模块使用方法详解(MD5,AES,Hmac,Diffie-Hellman加密)

    Node.js是基于V8 JavaScript引擎建立的服务器端应用程序,可以使用许多内置模块和第三方模块。其中加密模块非常常用和重要,提供了各种加密算法。本文将详细介绍Node.js crypto加密模块的使用方法,包括MD5、AES、Hmac、Diffie-Hellman加密,为想要了解Node.js加密的用户提供帮助。 1. 加载crypto模块 要使…

    node js 2023年6月8日
    00
  • node中socket.io的事件使用详解

    下面我将详细讲解“node中socket.io的事件使用详解”的攻略。 介绍 Socket.IO 是一个实时应用程序框架,可构建可靠的实时应用程序。它使实时和双向事件基于 WebSockets 易于使用,同时仍支持旧的连接机制,如 HTTP 长轮询。 Socket.IO 是基于事件的,它可以用来创建实时的数据传输、实时聊天应用程序等。 安装 使用 npm 包…

    node js 2023年6月8日
    00
  • 前端Electron新手入门教程详解

    前端Electron新手入门教程详解 Electron 是一个基于 Chromium 和 Node.js 的框架,可以用 Web 技术(HTML、CSS、JavaScript)构建跨平台的桌面应用程序。因为它支持 Windows、macOS、Linux 等多个操作系统,所以非常适合开发跨平台的桌面应用。本文将详细介绍如何使用 Electron 开发桌面应用程…

    node js 2023年6月8日
    00
  • 开发Node CLI构建微信小程序脚手架的示例

    下面是完整的攻略: 开发Node CLI构建微信小程序脚手架的示例 1. 确定开发工具和技术栈 作为一名网站开发者,我们需要使用一些工具来开发Node CLI。这里我们推荐使用Node.js作为开发环境,并借助yargs和fs-extra这两个依赖库进行开发。 2. 创建项目和安装依赖 首先,我们需要在本地创建一个新的Node.js项目,并安装yargs和f…

    node js 2023年6月8日
    00
  • 详解webpack打包nodejs项目(前端代码)

    下面是详解webpack打包nodejs项目(前端代码)的完整攻略: 1. 安装webpack 首先,我们需要在命令行中安装 webpack: npm install webpack –save-dev 2. 配置webpack 接下来,我们需要创建一个 webpack.config.js 的文件,并配置它。示例代码如下: const path = req…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部