当前位置: 首页 > article >正文

Node.js——模块化(模块的基本概念、模块化的规范、包与NPM)

目录

模块的基本概念

模块的定义

模块化的优点

Node.js 模块的分类 

模块的加载 

模块的作用域 

向外共享模块作用域内的成员 

模块化的规范

CommonJS

AMD 

CMD

ES6 Module

包与NPM

包的定义

NPM 包管理器 


模块的基本概念

模块的定义

  • 什么是模块?

        模块通常是指编程语言所提供的代码组织机制,利用此机制可将程序拆解为独立的、可分解,可更换的代码单元。      

  • 什么是模块化?

        模块化是一种设计思想,利用模块化可以把一个非常复杂的系统结构细化到具体的功能点,每个功能点看作一个模块,然后通过某种规则把这些小的模块组合到一起,构成模块化系统。 

模块化的优点

  1. 提高了代码复用性
  2. 提高了代码可维护性 
  3. 实现了代码按需加载

Node.js 模块的分类 

Node.js 根据模块的来源不同, 将模块分为了3大类:

  1. 内置模块 或者叫 核心(原生)模块: 由Node.js官方提供(如fs、http、net), 拥有最高的加载优先级.
  2. 自定义模块:用户创建的js文件都是自定义模块.
  3. 第三方模块: 由第三方开发, 并不是官方提供的内置模块, 使用前需要提前下载.

模块的加载 

  • 使用require()方法加载模块, 可以加载内置模块,自定义模块,第三方模块.

例如:

//加载 内置模块
const fs = require('fs');

//加载 自定义模块
const coconut = require('./coconut.js');  //路径可以省略文件的后缀名js

//加载 第三方模块
const timestamp = require('time-stamp');

  • 使用require()方法加载其它模块时,会执行加载模块中的代码.

coconut.js

主文件

运行得到结果

模块的作用域 

        和函数作用域类似, 在自定义模块中定义的变量, 方法等成员, 只能在当前模块内被访问, 这种模块级别的访问权限叫做模块作用域.

向外共享模块作用域内的成员 

        module对象

        在每个.js 自定义模块中都有一个module对象,里面存储了当前模块有关的信息. 例如:

  1. 在自定义模块中, 可以使用module.exports对象将模块内的成员导出, 让外界使用.
  2. 外界用require()方法导入自定义模块时, 得到的便是module.exports所指向的对象.

注意:

  • 使用require()方法导入模块时, 导入的结果,永远以module.exports指向的对象为准
  • 由于module.exports单词写起来不够简练, 为了简化代码, Node提供了exports对象. 默认情况下, exports和module.exports 指向的为同一个对象. 最终共享的结果, 还是以module.exports 为主. (二者可能会因为指针地址指向的问题而产生错误)

        使用require()方法导入模块时, 导入的结果,永远以module.exports指向的对象为准. 2.为了防止混乱, 建议不要在同一个模块中同时使用exports和module.exports.

模块化的规范

我们看JavaScript三种模块规范:

  • CommonJS:主要用于规范服务器端的编程,Node.js就是参照该规范实现
  • AMD:Asynchronous Module Definition 异步模块定义,使用异步方式加载模块 
  • CMD:Common Module Definition 通用模块定义,与AMD类似,但是在模块定义的方式和加载的时机上有所不同

CommonJS

        Node.js 遵循了CommonJS模块化规范, CommonJS规定了模块的特性各模块之间如何相互依赖.

         CommonJS规定:

  1. 每个模块内部, module 变量代表了当前模块.
  2. module 变量为一个对象,它的exports属性 (即module.exports) 为对外接口.
  3. 加载模块就是加载模块的module.exports属性. require()方法用于加载模块.

        加载模块是同步的,只有加载完成后才能执行后面的操作,也就是当要用到该模块了,现加载现用,不仅加载速度慢,而且还会导致性能、可用性、调试和跨域访问等问题。

        Node.js主要用于服务器编程,加载的模块文件一般都存在本地硬盘,加载起来比较快,不用考虑异步加载的方式,因此,CommonJS规范比较适用。然而,这并不适合在浏览器环境,同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。

AMD 

        AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

        这里介绍用require.js实现AMD规范的模块化:

  • 在html文件导入require.js
  • define()定义模块
  • require()加载模块。

 

define()函数

语法:

define([module-name?], [array-of-dependencies?], [module-factory-or-object]);

  • module-name:字符串,模块名称(可选). 如果省略第一个参数,这样就定义了一个匿名模块,这时候模块文件的文件名就是模块标识
  • array-of-dependencies: 是我们要载入的依赖模块(可选),使用相对路径。注意是数组格式
  • module-factory-or-object: 工厂方法或者一个对象(必选).

        当define函数执行时,它首先会异步的去调用第二个参数中列出的依赖模块,并且还要当做形参传到factory中,对于依赖的模块提前执行,依赖前置。

也就是:需要先加载完毕所有的依赖模块, 然后才能运行你定义的模块.

如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。 如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中. 

require()函数

        require()语句加载模块,但是不同于CommonJS,它要求两个参数.

语法: require([module], callback);

  • 第一个参数[module],是一个数组,里面的成员为字符串类型, 也就是要加载的模块名
  • 第二个参数callback,则是加载成功之后的回调函数。注意要有参数来接收模块共享的成员.

CMD

        CMD (Common Module Definition), 是seajs推崇的规范,CMD则是依赖就近,用的时候再require.

        CMD与AMD一样,也是采用特定的define()函数来定义,用require()方式来引用模块

ES6 Module

        ES6标准发布后,module成为标准,标准使用是以export指令导出接口,以import引入模块.

        但是在我们一贯的node模块中,我们依然采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口。

        在 Node.js 环境中默认使用的是 CommonJS 规范。需要使用 require 语句进行导入。import 是 ES6 中的模块化写法,CommonJS 模块与 ES6 模块不兼容.

包与NPM

包的定义

Node.js中的包

        包是包含js文件和其他附加信息的整体,某种意义上来说,包是模块的集合, 也就是我们说的第三方模块.

        模块是按照CommonJS规范写的js文件。

NPM官网 https://www.npmjs.com/ 是全球最大的包共享平台. 从这个网站上可以查找到你想要的包.

同时通过 https://registry.npmjs.org/ 服务器共享所有的包. 也就是我们能从这个地址下载包.

因为国内官网无法访问, 所以可以使用国内的阿里云镜像. https://npmmirror.com/

NPM 包管理器 

        Node Packaged Manager (NPM) 是管理包的工具. 这个包管理工具随着Node.js的安装一起安装到了用户的电脑.

        可以通过在终端中执行npm -v 命令来查看自己电脑的NPM版本.


END 



http://www.kler.cn/a/526477.html

相关文章:

  • 【视频+图文详解】HTML基础4-html标签的基本使用
  • 数据分析系列--⑤RapidMiner进行关联分析(中文数据案例)
  • 物联网智能项目之——智能家居项目的实现!
  • java+vue项目部署记录
  • DeepSeek大模型技术解析:从架构到应用的全面探索
  • 【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)
  • 傅里叶分析之掐死教程
  • Zookeeper入门部署(单点与集群)
  • 《Chart.js 饼图:深度解析与最佳实践指南》
  • 【新春特辑】2025年1月科技浪潮中的AI最新时事与科技趋势
  • autosar bsw 的关键模块
  • Nuitka打包python脚本
  • C++中常用的十大排序方法之1——冒泡排序
  • CF 761A.Dasha and Stairs(Java实现)
  • deb安装失败后,无法再安装别的包的解决方案
  • MyBatis 入门
  • 深度学习 Pytorch 神经网络的损失函数
  • AIGC(生成式AI)试用 20 -- deepseek 初识
  • 2024-10-26 进程间通信
  • Python 梯度下降法(三):Adagrad Optimize
  • 第27章 苏睿所长的关键沟通
  • CS1.5在Win10下有声音黑屏无图像如何设置
  • dify实现原理分析-rag-数据检索的实现
  • 基于强化学习的机器人自主导航与避障
  • 初阶数据结构:链表(二)
  • 电梯系统的UML文档14