「node学习笔记」node.js的模块实现及编译

博读代码 博读代码     2022-11-28     308

关键词:

前言

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。

为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在 Node 环境中,一个 .js 文件就称之为一个模块(module)。


一、使用模块的好处

使用模块最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括 Node 内置的模块和来自第三方的模块。​

使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。


二、Node的模块实现

在 Node 中引入模块,需要经历如下三个步骤:

  • 路径分析
  • 文件定位
  • 编译执行


在 Node 中,模块分为两类:

第一类是 Node 自身提供的模块,称为核心模块:fs、http等,就像 java 中的jdk 提供的核心类一样。

第二类是用户编写的模块,称为文件模块

核心模块部分在 Node 源代码的编译过程中,编译进了二进制执行文件。在 Node 进程启动时,核心模块就被直接加载进内存,所以这部分的模块引入时,文件定位和编译执行这两个步骤可以省略掉,并且在路径分析中优先判断,所以它的加载速度是最快的。

文件模块在运行时动态加载,需要完整的路径分析,文件定位,编译执行过程,加载速度比核心模块慢。

以上介绍了模块加载过程和模块的类别划分,下面我们来看看 Node 加载模块的具体过程,如下图:

「Node学习笔记」Node.js的模块实现及编译_Node

Node 为了优化加载模块的速度,也像浏览器一样引入了缓存,对加载过的模块会保存到缓存内,下次再次加载时就会命中缓存,节省了对相同模块的多次重复加载。模块加载前会将需要加载的模块名转为完整路径名,查找到模块后将完整路径名保存到缓存,下次再次加载该路径模块时就可以直接从缓存中取得。

在 require 加载模块时,require 参数的标识符可以以文件类型结尾 require(“./test.js”),也可以省略文件类型 require(“./test”)。

对于省略类型的第二种写法,Node 首先会认为它是一个 .js 文件,如果没有查找到该 js 文件,然后会去查找 .json 文件,如果还没有查找到该 json 文件,最后会去查找 .node 文件,如果连 .node 文件都没有查找到,就该抛异常了。

Node 在执行 require 加载模块时是线程阻塞的,大家都知道 Node 是单线程执行的,如果长期阻塞的话系统其它任务就得不到执行了,所以为了加快 require 模块的加载,如果不是 .js 文件的话,在 require 的时候就把文件类型加上,这样 Node 就不会再去一一尝试了。


三、模块编译

在 Node 中,每个文件模块都是一个对象,具体定义如下:

「Node学习笔记」Node.js的模块实现及编译_Node_02


编译和执行是引入文件模块的最后一个阶段。

定位到具体的文件后,Node 会新建一个模块对象,然后根据路径载入并编译。

对于不同的文件扩展名,其载入方法也有所不同,具体如下:

  • .js文件:通过 fs 模块同步读取文件后编译执行。
  • .json文件:通过 fs 模块同步读取文件后,用 JSON.parse() 解析返回结果。
  • .node文件:这是用 C/C++ 编写的扩展文件,通过 dlopen() 方法加载最后编译生成的文件。
  • 其余扩展名的文件:它们都被当作 .js 文件载入。

每一个编译成功的模块都会将其文件路径作为索引缓存在 Module._cache 对象上,以提高二次引入的性能。

我们都知道,在浏览器中编写的 js 文件,如果变量定义不是在函数或对象内,就会存在污染全局变量的情况,例如下面这种方式定义的变量:

<script>

a = test;

</script>

等同于 window.a = ‘test’;


但我们在 Node 中的每个 .js 模块内并没有做任何其它处理,定义的变量怎么就不会污染全局环境了呢?还有在 Node 的模块内,怎么就可以直接使用module、require、exports、filename、 dirname等对象呢?

事实上,在编译的过程中,Node 对获取的 JavaScript 文件内容进行了头尾包装。

例如我们一开始写的 DateUtil.js,如下:

「Node学习笔记」Node.js的模块实现及编译_前端_03「Node学习笔记」Node.js的模块实现及编译_前端_04


编译包装后的文件是下面这样的:

「Node学习笔记」Node.js的模块实现及编译_Node_05

这样每个模块之间就进行了作用域隔离。


以上就是本期关于 Node.js 模块实现的分享,希望能给大家带来帮助。

下期给大家分享更多实战中的点滴,如果大家对此感兴趣,欢迎各位关注、留言,大家的支持就是我的动力!

nodejs学习笔记---简介及安装node.js开发环境

目录学习资料简介安装Node.jsnpm简介开发工具SublimeNode.js开发环境配置扩展:安装多版本管理器 学习资料  1.深入浅出Node.js http://www.infoq.com/cn/minibooks/nodejs  2.Node.js开发指南 简介(只捡了我觉得重要的)Node.js是让J... 查看详情

nodejs学习笔记---简介及安装node.js开发环境

目录学习资料简介安装Node.jsnpm简介开发工具SublimeNode.js开发环境配置扩展:安装多版本管理器 学习资料  1.深入浅出Node.js http://www.infoq.com/cn/minibooks/nodejs  2.Node.js开发指南 简介(只捡了我觉得重要的)Node.js是让J... 查看详情

node.js学习笔记-模块化开发(代码片段)

JavaScript开发过程中存在文件依赖和命名冲突问题,因此要采用模块化开发的方式。软件当中的模块化开发每个JavaScript文件就是一个模块,模块内部的变量无法在外部进行访问。有两种方式可以实现访问。文件b中访问a中... 查看详情

express框架解析——学习笔记

用express脚手架组件的程序目录结构如下图:/app.js主程序配置,启动文件。/package.json:存储着工程的信息及模块依赖,当在dependencies中添加依赖的模块时,运行npminstall,npm会检查当前目录下的package.json,并自动安装所有指定的... 查看详情

node.js学习笔记——模块调用

js创建一个类然后在另一程序中实例化使用这个类1.创建一个User类//--------------User.js--------------  function  User(id,name,age){    this.id=id;    this.name=name;  查看详情

node.js开发实战详解的内容体系

...orld的实现及异步编程思想等。第2章主要介绍了Node.js中的模块的概念,以及Node.js中exports和module.exports之间的联系和区别。Node.js中的NPM模块包含request、socket.io、express、jade和forever模块。Node.js中的设计模式包含单例、适配器和装... 查看详情

node.js学习笔记一

node.js node是平台也是语言。它是平台或者运行环境,能够让js在服务器端运行,因为它封装V8引擎(引擎,能够将js代码解析成计算机能够懂得语言),能够让js运行在其他的平台上面,而不只是运行在浏览器上。它是服务器... 查看详情

千锋node.js学习笔记(代码片段)

千锋Node.js学习笔记文章目录千锋Node.js学习笔记写在前面1.认识Node.js2.NVM3.NPM4.NRM5.NPX6.模块/包与CommonJS7.常用内置模块1.url2.querystring3.http4.跨域jsonpcorsmiddleware(http-proxy-middleware)5.爬虫6.events7.FileSystem8.St 查看详情

「node学习笔记」浅谈node.js读写xlsx文件

前言先给大家简单介绍一下,这是一个读写xlsx文件的功能,主要帮助我们打印或是读写一些数据。应用场景:以消费订单为例,当客户需要导出网站的累计消费金额时,我们需要查看流水账,作为开发人员可以将数据在node的服... 查看详情

node.js之web学习笔记(代码片段)

http模块入门Node.js提供了系统模块http用来写服务端代码。http模块是系统核心模块,不需要下载只需要直接引入即可,引入代码如下:varhtttp=require('http');创建简单的服务端代码如下://第一步,引入http... 查看详情

node.js笔记:serialport(串口)模块使用(代码片段)

文章目录目的模块安装基础使用扫描端口打开端口发送数据接收数据错误处理数据解析器SerialPort类构造方法属性事件方法命令行工具总结目的上位机与各种电路模块间常常采用串口进行通讯,Node.js中可以使用SerialPort模块操... 查看详情

nodejs学习笔记一

一、node版本的更新命令node有一个模块叫n,是专门用来管理node.js的版本的。首先安装n模块:npminstall-gn第二步:升级node.js到最新稳定版nstablen后面也可以跟随版本号比如:nv0.10.26或n0.10.26分享几个npm的常用命令npm-v#显示版本,检... 查看详情

node.js学习笔记——创建第一个应用

  巧妇难为无米之炊。要学习node.js,当然必须先有node.js环境(可以去官网http://nodejs.cn/下载安装),如果还是不懂怎么配置开发环境,度娘会告诉你一切。  安装完成环境之后,先别急着开发。在开发之前,为了更清晰的... 查看详情

node.js学习笔记之调用函数

本文件和从其它模块引入函数;从其他模块引入分只支持引入一个函数和多个 这两种例:test.js为主函数varhttp=require(‘http‘);http.createServer(function(request,response){response.writeHead(200,{‘Content-Type‘:‘text/html‘})func1(response);//调用... 查看详情

node.js学习笔记——回调函数

  Node.js异步编程的直接体现就是回调。  那什么是回调呢?回调指的是将一个函数作为参数传递给另一个函数,并且通常在第一个函数完成后被调用。需要指明的是,回调函数不是由该函数的实现方直接调用,而是在特定... 查看详情

node.js学习笔记_模拟路由

 路由就是浏览器输入url地址,服务端根据对url地址的解析,访问对应的代码模块。var    http    =    require(‘http‘);var    url    =&nb 查看详情

node学习笔记文件监听的实现

前言开发云盘的时候,使用到了依赖于node.js的chokidar做本地文件监听,获取文件修改的触发事件。下面来给大家介绍一下涉及的知识点以及实现过程。知识点chokidar.watch(paths,[options])返回一个chokidar构造监听实例参数:paths一个字... 查看详情

node.js--学习笔记

简单的说Node.js就是运行在服务端的JavaScript。Node.js是一个基于ChromeJavaScript运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。使用的版本我们... 查看详情