简单模拟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日

相关文章

  • Vue页面渲染中key的应用实例教程

    下面是关于“Vue页面渲染中key的应用实例教程”的完整攻略: 什么是key key是一个特殊的属性,用于协助Vue区分每个节点的身份,以便在不同的渲染情况下识别其应有的状态。在Vue中,key主要用于优化虚拟DOM的渲染效率。 常见应用场景 列表渲染 在Vue中,当使用v-for指令进行列表渲染时,每个元素都需要指定一个唯一的key,以便Vue能够正确地追…

    node js 2023年6月8日
    00
  • node.js实现端口转发

    下面是关于node.js实现端口转发的完整攻略。 什么是端口转发 在计算机网络中,端口是一种特定的标识符,用于标识不同的进程或服务。每个进程或服务都会占用一个特定的端口来进行通信。而端口转发则是将一台计算机的某个端口的流量转发到另一台计算机的某个端口上的技术。 使用node.js实现端口转发的步骤 要使用node.js来实现端口转发,需要进行以下步骤: 1.…

    node js 2023年6月8日
    00
  • node.js基于socket.io快速实现一个实时通讯应用

    下面详细讲解“node.js基于socket.io快速实现一个实时通讯应用”的完整攻略。 简介 Socket.io 是一个优秀的跨浏览器的 WebSocket 实现,它解决了 WebSocket 在使用过程中的兼容性问题,并且实现了多种应用级别的实时通信协议。使用 Node.js 和 Socket.io 可以快速实现一个实时通讯应用。 准备 首先,你需要安装…

    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
  • 解决vue eslint开发严格模式警告错误的问题

    下面是解决vue eslint开发严格模式警告错误的问题的完整攻略,具体步骤如下: 1. 理解严格模式 在解决问题之前,我们需要先了解一下什么是严格模式。Vue默认启用了ESLint严格模式,用于捕获一些潜在的问题。这种模式下会对一些非规范行为进行报错提示,提高了代码的质量和可维护性。但是对于一些新手或者还不是很熟悉语法的人来说,这些警告可能会显得很繁琐,并…

    node js 2023年6月9日
    00
  • 三分钟教会你用nodejs操作mysql数据库

    使用 Node.js 操作 MySQL 数据库是一件非常重要的事情,特别是对于 Node.js 开发人员来说,因为这可以帮助他们更好地处理和管理数据。在下面的对话中,我将分享一个简单的三分钟攻略,以向您展示如何使用 Node.js 操作 MySQL 数据库。 1. 安装 MySQL 首先,我们需要在本地计算机上安装 MySQL。MySQL 是一个流行的开源数…

    node js 2023年6月8日
    00
  • nodejs之get/post请求的几种方式小结

    下面是“nodejs之get/post请求的几种方式小结”的完整攻略。 简介 在 Node.js 服务器中,我们经常需要处理来自客户端的 HTTP 请求,其中常见的请求方式有 GET 和 POST 请求。在本文中,我们将会向你展示如何使用 Node.js 处理 GET/POST 请求以及几种常用的方式。 处理 GET 请求 1. 使用 querystring…

    node js 2023年6月8日
    00
  • Node.js基础入门之缓存区与文件操作详解

    《Node.js基础入门之缓存区与文件操作详解》是一篇介绍Node.js中缓存区和文件操作的基础内容的教程。本篇攻略主要分为以下几部分: Node.js中的缓存区是什么?如何使用缓存区? Node.js中的文件操作是什么?如何读写文件? 两条示例说明 1.Node.js中的缓存区 1.1 什么是缓存区? 在Node.js中,缓存区指代的是一个用于临时存储数据…

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