JS | CommonJS、AMD、CMD、ES6-Module、UMD五种JS模块化规范

目录

前言

一、CommonJS 模块化规范

二、ES6 模块化规范

三、AMD 模块化规范

四、CMD 模块化规范

五、UMD模块化规范


前言

这三个规范都是为Js模块化加载而生的,使模块能够按需加载,使系统同庞杂的代码得到组织和管理。模块化的管理代码使多人开发得到了更好的合作。

一、CommonJS 模块化规范

是一种为JS的表现指定的规范,它希望js可以运行在任何地方,更多的说的是服务端模块规范,Node.js采用了这个规范。

CommonJS主要用于服务器端,‌Node.js是其主要实践者。

核心思想

一个单独文件就是一个模块,通过require方法来同步加载要依赖的模块,然后通过extports或者module.exports来导出需要暴露的接口。

require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;

(1) 每一个文件都是一个模块,每一个模块都有一个独立的作用域,文件内的变量,函数都是私有的,其他文件不可使用(除非赋值到 global上)

(2)每个模块内部,module变量代表当前模块

(3)每个文件对外的接口是 module.exports 属性

(4) require用于引用其他模块,实际获得的是其他模块的module.exports这个属性 

优点:服务器端模块重用,NPM中模块包多,有将近20万个。

缺点:加载模块是同步的,只有加载完成后才能执行后面的操作,也就是当要用到该模块了,现加载现用,不仅加载速度慢,而且还会导致性能、可用性、调试和跨域访问等问题。Node.js主要用于服务器编程,加载的模块文件一般都存在本地硬盘,加载起来比较快,不用考虑异步加载的方式,因此,CommonJS规范比较适用。然而,这并不适合在浏览器环境,同步意味着阻塞加载,浏览器资源是异步加载的,因此,有了AMD CMD解决方案。

实现:服务器端的 Node.js;Browserify,浏览器端的 CommonJS 实现,可以使用 NPM 的模块,但是编译打包后的 文件体积可能很大;modules-webmake,类似Browserify,还不如 Browserify 灵活;wreq,Browserify 的前身;

小结:commonjs模块化规范

CommonJS规范是同步加载模块,也就是说,在执行到require调用的时候,会立即加载并执行模块。这种同步的方式对服务器端不存在问题,因为所有的模块都在本地,可以直接加载。但是对于浏览器端,模块可能需要通过网络加载,这就需要异步加载,因此,在浏览器端,AMD和CMD规范得到了广泛的应用。

以下是CommonJS规范的一个简单示例:

假设我们有两个文件,一个是math.js,另一个是main.js

math.js:

// math.js
exports.add = function(a, b) {return a + b;
};exports.multiply = function(a, b) {return a * b;
};

main.js:

// main.js
var math = require('./math');console.log('2 + 3 = ' + math.add(2, 3));
console.log('2 * 3 = ' + math.multiply(2, 3));

 在math.js中,我们使用exports对象来暴露模块接口,在main.js中,我们使用require函数来加载math.js模块,并使用其提供的方法。 在Node.js环境中,你可以直接运行这两个文件,因为Node.js采用了CommonJS规范。但是在浏览器环境中,你需要使用像Browserify这样的工具来将CommonJS格式的代码转换成可以在浏览器中运行的格式。

二、ES6 模块化规范

ES6中的Module规范定义了JavaScript的模块。模块功能主要由关键字exportimport实现。

ES6 模块化适用于浏览器端和服务器端,是JavaScript语言的最新版本,通过importexport语句实现模块化。

export用于定义模块对外暴露的接口,可以用来导出变量、函数、类等。

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

import用于从其他模块导入需要的接口。 

// app.js
import { add, subtract } from './math.js';console.log(add(1, 2)); // 输出3
console.log(subtract(10, 5)); // 输出5

模块可以导出单个值,也可以全部导出。

// math.js
function add(a, b) {return a + b;
}
function subtract(a, b) {return a - b;
}
export { add, subtract };// app.js
import * as math from './math.js';console.log(math.add(1, 2)); // 输出3
console.log(math.subtract(10, 5)); // 输出5

 默认导出(default export)只允许每个模块有一个。

// math.js
const add = (a, b) => a + b;
export default add;// app.js
import math from './math.js';console.log(math(1, 2)); // 输出3

以上是ES6 Module的基本使用方法。

参考:export default 和 export之间的区别-CSDN博客

三、AMD 模块化规范

鉴于浏览器的特殊情况,又出现了一个规范,这个规范呢可以实现异步加载依赖模块,并且会提前加载,那就是AMD规范。——(Asynchromous Module Definition - 异步模块定义)

AMD主要用于浏览器端,‌RequireJS是其主要实践者。通过define()require()函数实现模块化。

其核心接口是:define(id?, dependencies?, factory) ,它要在声明模块的时候指定所有的依赖 dependencies ,并且还要当做形参传到factory 中,对于依赖的模块提前执行,依赖前置。

define("module", ["dep1", "dep2"], function(d1, d2) {return someExportedValue;
});
require(["module", "../file"], function(module, file) { /* ...*/ });

优点:在浏览器环境中异步加载模块;并行加载多个模块;

缺点:开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅;不符合通用的模块化思维方式,是一种妥协的实现;

实现:RequireJS; curl;

小结:‌AMD规范

AMD规范的定义和基本概念‌

AMD(Asynchronous Module Definition)‌是一种异步模块定义规范,主要用于浏览器端的JavaScript模块化。它是由‌RequireJS的作者‌James Burke提出的一种模块化规范,旨在解决浏览器环境中多个JavaScript文件依赖关系的问题,并实现异步加载模块。

AMD规范的基本语法

在AMD规范中,每个模块都必须通过define函数定义。define函数可以接收两个到四个参数:第一个参数是模块的名字,第二个参数是一个数组,声明模块的依赖项,第三个参数是一个函数,该函数的参数与前面的依赖项一一对应,用于定义模块的导出成员。例如:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {exports.verb = function() {return beta.verb();}
});

AMD规范的使用场景和优缺点

AMD规范适合在浏览器环境中异步加载模块,可以并行加载多个模块并按需加载。RequireJS是实现AMD规范的主要工具,它解决了多个JavaScript文件依赖关系的问题,使得浏览器可以异步加载模块,从而不会阻塞页面的渲染。

优点:

  • 适合在浏览器环境中异步加载模块。
  • 可以并行加载多个模块。
  • 按需加载模块。

缺点:

  • 需要第三方库(如RequireJS)支持。
  • 模块划分细致时,文件请求频繁。

AMD规范与其他模块化规范的对比

AMD规范与CMD规范和CommonJS规范相比,主要区别在于依赖模块的执行时机和处理方式不同。AMD规范是异步加载模块,而CMD规范是按需加载模块。CommonJS规范适用于服务器端,同步加载模块。

AMD规范通过define方法定义模块,通过require方法加载模块,而CMD规范也是通过define方法定义模块,但执行时机不同。CommonJS规范通过require命令加载模块,并通过module.exportsexports对外暴露接口。 

四、CMD 模块化规范

Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。——(Common Module Definition - 公共模块定义)

define(function(require, exports, module) {var $ = require('jquery');var Spinning = require('./spinning');exports.doSomething = ...module.exports = ...
})

优点:依赖就近,延迟执行 可以很容易在 Node.js 中运行;

缺点:依赖 SPM 打包,模块的加载逻辑偏重;

实现:Sea.js ;coolie

小结:CMD规范(Common Module Definition)是一种模块定义规范,它明确了模块的基本书写格式和基本交互规则。‌ CMD规范专门用于浏览器端,模块的加载是异步的,只有在模块使用时才会加载执行。CMD规范整合了CommonJS
和AMD规范的特点,提供了一个简单且与Modules规范保持较大兼容性的模块化解决方案。

在CMD规范中,一个模块就是一个文件,通过define关键字来定义模块。基本的格式是define(factory);,其中define是一个全局函数,factory可以是函数、对象或字符串。当factory为函数时,它表示模块的构造方法,执行该构造方法可以得到模块向外提供的接口。factory方法在执行时,默认会传入三个参数:require、exports和module。这三个参数分别用于引入其他模块、导出模块的内容以及获取当前模块的信息。

此外,CMD规范推荐一个文件对应一个模块,因此经常使用文件名作为模块的标识。依赖就近的原则也被推荐,即在factory函数中直接写入依赖,而不是在define的参数中指定。这种做法使得代码更加直观和易于维护。

SeaJS是遵循CMD规范的代表库之一,它提供了一个轻量级的模块加载器,使得开发者能够更加方便地使用CMD规范的模块化编程。通过SeaJS,开发者可以更加轻松地实现模块的异步加载和使用,从而提高代码的加载速度和质量‌。

五、UMD模块化规范

UMD模块化规范是AMD和CommonJS的糅合)。

UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。

在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。

(function (window, factory) {if (typeof exports === 'object') {module.exports = factory();} else if (typeof define === 'function' && define.amd) {define(factory);} else {window.eventUtil = factory();}
})(this, function () {//module ...
});

总结:

JavaScript的模块化规范主要包括​ CommonJS、AMD、CMD、ES6模块化以及UMD。 ​

  • CommonJS‌:主要应用于服务器端,每个文件都被视为一个模块,通过require函数加载模块,使用module.exportsexports对象导出模块内容。这种规范适合于Node.js环境,因为它基于服务器端JavaScript的运行环境设计,简单直观,但不适合浏览器环境,因为它采用同步加载方式‌。

  • AMD (Asynchronous Module Definition)‌:由RequireJS推广,采用异步方式加载模块,支持通过指定回调函数定义依赖模块。这种方式解决了CommonJS在浏览器环境下同步加载的问题,允许模块加载不会阻塞页面的渲染‌。

  • CMD (Common Module Definition)‌:由SeaJS推广,与AMD类似,但也支持非异步加载。它的使用方式与AMD有所不同,但同样旨在解决模块依赖和异步加载的问题‌。

  • ES6模块化‌:ECMAScript 2015引入的原生模块系统,使用importexport关键字实现模块的导入和导出。ES6模块支持静态和动态导入,具有静态解析、异步加载和更好的兼容性等优点,成为现代前端开发中最流行的模块化规范‌。

  • UMD‌:是AMD和CommonJS的混合体,旨在同时支持Node.js和浏览器环境。UMD会根据运行环境自动选择使用CommonJS或AMD的模块加载方式‌。

这些模块化规范各有特点,适用于不同的使用场景。CommonJS适合服务器端开发,而ES6模块化则更适合现代前端开发,提供了更好的异步加载和兼容性。AMD和CMD规范则主要解决了浏览器环境下模块的异步加载问题。UMD则是一种折中的解决方案,旨在同时支持Node.js和浏览器环境‌。


● 参考资料 ●

AMD规范、CMD规范、CommonJS - 简书 | JavaScript的模块规范有哪些-PHP中文网

JS中的几种模块化规范(CommonJS、AMD、CMD、ES6 Module)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【宠物狗狗数据集】 犬类品种识别 宠物狗检测 深度学习 目标检测(含数据集)

一、背景意义 随着人们对宠物狗的喜爱日益增加,犬种的多样性也逐渐受到重视。狗狗不仅是家庭的好伴侣,更在多个领域中发挥着重要作用,如导盲、搜救、疗愈等。因此,准确识别和分类各种犬种显得尤为重要。传统的犬种识别方法往往依赖…

移远通信闪耀2024香港秋灯展,以丰富的Matter产品及方案推动智能家居产业发展

10月27-30日,2024香港国际秋季灯饰展在香港会议展览中心盛大开展。 作为全球领先的物联网整体解决方案供应商,移远通信再次亮相,并重点展示了旗下支持Matter协议以及亚马逊ACK ( Alexa Connect Kit ) SDK for Matter方案的Wi-Fi模组、低功耗蓝…

虚拟机桥接模式连不上,无法进行SSH等远程操作

说明:以下情况在window10上遇到,解决后顺便做了个笔记,以防后续再次用到,也给同道中人提供一个解决方案 一、首先按照以下步骤进行检查 1、是否连接了对应的wifi 2、是否设置了桥接模式 3、上述1、2确认无误的情况下请查看右上…

ApsaraMQ Serverless 能力再升级,事件驱动架构赋能 AI 应用

本文整理于 2024 年云栖大会阿里云智能集团高级技术专家金吉祥(牟羽)带来的主题演讲《ApsaraMQ Serverless 能力再升级,事件驱动架构赋能 AI 应用》 云消息队列 ApsaraMQ 全系列产品 Serverless 化,支持按量付费、自适应弹性、跨可…

一款专业获取 iOS 设备的 UDID 工具|一键获取iPhone iPad设备的 UDID

什么是UDID? UDID,是iOS设备的一个唯一识别码,每台iOS设备都有一个独一无二的编码,这个编码,我们称之为识别码,也叫做UDID( Unique Device Identifier) 扫描后系统提示输入密码&am…

IDEA连接EXPRESS版本的SQL server数据库

我安装的版本是SQL2019-SSEI-Expr.exe 也就是EXPRESS版本的SQL Server安排非常简单和快速。 但是默认没有启动sa用户。 启动sa用户名密码登录 默认安装完以后没有启用。 使用Miscrosoft SQL Server Management Studio 使用Windows身份连接后。 在安全性》登录名中找到sa并修改…

大模型,多模态大模型面试问题【计算图,LLama,交叉熵,SiLU,RLHF】

大模型,多模态大模型面试问题【计算图,LLama,交叉熵,SiLU,RLHF】 问题一:讲一讲计算图中pytorch是什么,TensorFlow是什么?1. PyTorch2. TensorFlow区别总结 问题二:Llama…

【AIGC】2024-arXiv-Lumiere:视频生成的时空扩散模型

2024-arXiv-Lumiere: A Space-Time Diffusion Model for Video Generation Lumiere:视频生成的时空扩散模型摘要1. 引言2. 相关工作3. Lumiere3.1 时空 U-Net (STUnet)3.2 空间超分辨率的多重扩散 4. 应用4.1 风格化生成4.2 条件生成 5. 评估和比较5.1 定性评估5.2 …

隨筆 20241025 Kafka数据一致性的韭菜比喻

在Kafka中,数据一致性是通过Leader和Follower副本之间的协调来实现的。为了更容易理解这个复杂的概念,我们可以用韭菜作为比喻。 韭菜的角色 Leader韭菜:代表数据的主导者,它负责更新和维护最新的数据。Follower韭菜&#xff1a…

【CPN TOOLS建模学习】设置变迁的属性

使用Tab键在属性之间进行切换 与一个变迁相关联的四个铭文,均为可选项: 变迁名称守卫(Guard)时间代码段 变迁延迟必须是一个正整数表达式。该表达式前面加上,这意味着时间铭文的形式为 delayexpr。在添加时间铭文之前,铭文的默…

标准正态分布的数据 tensorflow 实现正态分布图,python 编程,数据分析和人工智能...

登录后复制 import tensorflow as tfimport matplotlib.pyplot as plt# 设置随机种子以获得可重复的结果tf.random.set_seed(42)# 生成正态分布的数据# mean0 和 stddev1 表示生成标准正态分布的数据# shape(1000,) 表示生成1000个数据点data tf.random.normal(mean0, stddev1…

005 IP地址的分类

拓扑结构如下 两台主机处于同一个网关下,通过ping命令检测,可以连通 &nbps; 拓扑结构如下 使用ping 检查两台电脑是否相通, 因为网络号不一样,表示两台电脑不在同一个网络,因此无法连通 拓扑结构如下 不在同一网络的PC要相…

HTML--浮动布局练习

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 整个浏览器页…

后台管理系统的通用权限解决方案(二)SpringBoot整合Swagger Springfox实现接口日志文档

文章目录 1 Swagger介绍2 Swagger常用注解3 Swagger使用案例 1 Swagger介绍 使用Swagger&#xff0c;我们只需要按照它的规范去定义接口及接口相关的信息&#xff0c;再通过Swagger衍生出来的一系列项目和工具&#xff0c;就可以做到生成各种格式的接口文档&#xff0c;生成多…

【Spring框架】Spring框架的开发方式

目录 Spring框架开发方式前言具体案例导入依赖创建数据库表结构创建实体类编写持久层接口和实现类编写业务层接口和实现类配置文件的编写 IoC注解开发注解开发入门&#xff08;半注解&#xff09;IoC常用注解Spring纯注解方式开发 Spring整合JUnit测试 Spring框架开发方式 前言…

Redis数据安全_持久化机制

由于Redis的数据都存放在内存中&#xff0c;如果没有配置持久化&#xff0c;Redis重启后数据就全丢失了&#xff0c;于是需要开启Redis的持久化功能&#xff0c;将数据保存到磁盘上&#xff0c;当Redis重启后&#xff0c;可以从磁盘中恢复数据。 持久化机制概述 对于Redis而言…

Golang | Leetcode Golang题解之第519题随机翻转矩阵

题目&#xff1a; 题解&#xff1a; type Solution struct {m, n, total intmp map[int]int }func Constructor(m, n int) Solution {return Solution{m, n, m * n, map[int]int{}} }func (s *Solution) Flip() (ans []int) {x : rand.Intn(s.total)s.total--if y, o…

【电子通识】四线制电阻屏怎么判断是哪一路出现异常?

在文章【电子通识】四线电阻屏原理中我们聊了一下四线电阻屏触摸的原理,如电阻屏结构、如何计算坐标等方面。 那么在实际的问题分析中,如果是屏硬件问题,那我们如何去判断到底是X还是Y出现异常或是说X+还是X-,是Y+还是Y-出现问题呢? 首先要知道,XY轴为什么会出问题,其实…

高效文本编辑与导航:Vim中的三种基本模式及粘滞位的深度解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…