Javascript模块规范(CommonJS、AMD、CMD、ESM)

带你全面理解JS模块的标准(AMD、CMD、COMMON.JS 、 UMD、ESM) 在前端的世界演变里,有着几种JS的模块规范,从出现的序言来说就是: ①amd ②cmd ③common.js ④ umd ⑤ esm 现在Vue框架里面都是遵守esm规范,不得不说esm是目前最好最流行的一种js规范了 amd - 浏览器中的js模块化解决方案 AMD 全称是 Async Module Definition -中文: 异步模块化定 义 require.js是AMD模块规范的一个具体实现 核心是通过define方法对无序的代码进行有序的模块化定义,通过require方法实现代码的模块化加 阅读详情

​CommonJS

node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。

var math = require('math');
math.add(2,3); // 5    

CommonJS的特点

  • 所有代码都运行在模块作用域,不会污染全局作用域;
  • 模块是同步加载的,即只有加载完成,才能执行后面的操作;
  • 模块在首次执行后就会缓存,再次加载只返回缓存结果,如果想要再次执行,可清除缓存;
  • CommonJS输出是值的拷贝(即,require返回的值是被输出的值的拷贝,模块内部的变化也不会影响这个值)。

AMD

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

require([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

// a.js
//define可以传入三个参数,分别是字符串-模块名、数组-依赖模块、函数-回调函数
define(function(){
    return 1;
})

// b.js
//数组中声明需要加载的模块,可以是模块名、js文件路径
require(['a'], function(a){
    console.log(a);// 1
});

 对于依赖的模块,AMD推崇依赖前置,提前执行。也就是说,在define方法里传入的依赖模块(数组),会在一开始就下载并执行。

CMD

CMD推崇依赖就近,延迟执行。可以把你的依赖写进代码的任意一行,如下:

define(function(require, exports, module) {
  var a = require('./a');
  a.doSomething();
  var b = require('./b');
  b.doSomething();
})

这个规范实际上是为了Seajs的推广然后搞出来的。那么看看SeaJS是怎么回事儿吧,基本就是知道这个规范了。

同样Seajs也是预加载依赖js跟AMD的规范在预加载这一点上是相同的,明显不同的地方是调用,和声明依赖的地方。AMD和CMD都是用difine和require,但是CMD标准倾向于在使用过程中提出依赖,就是不管代码写到哪突然发现需要依赖另一个模块,那就在当前代码用require引入就可以了,规范会帮你搞定预加载,你随便写就可以了。但是AMD标准让你必须提前在头部依赖参数部分写好(没有写好? 倒回去写好咯)。这就是最明显的区别。

ES6

ES6 Module是ES6中规定的模块体系,相比上面提到的规范, ES6 Module有更多的优势,有望成为浏览器和服务器通用的模块解决方案。

Es6通过import、export实现模块的输入输出。其中import命令用于输入其他模块提供的功能,export命令用于规定模块的对外接口。

// a.js
export const a = 1
export const fn = () => 2

// b.js
export default const fn2 = (value) => value

// index.js
import { a, fn } from './a.js'
import fn2 from './b.js'

console.log(a) // 1
console.log(fn()) // 2
console.log(fn1(10)) // 10

ES6 Module的特点(对比CommonJS)

  • CommonJS模块是运行时加载,ES6 Module是编译时输出接口;
  • CommonJS加载的是整个模块,将所有的接口全部加载进来,ES6 Module可以单独加载其中的某个接口;
  • CommonJS输出是值的拷贝,ES6 Module输出的是值的引用,被输出模块的内部的改变会影响引用的改变;
  • CommonJS this指向当前模块,ES6 Module this指向undefined;

怎么理解上面的运行时加载/编译时输出接口、值的拷贝/值的引用?

commonJS例子

//calculator.js
var count=0;
module.exports={
  count:count,
  ADD:function (a,b) {
      count+=1;
      return a+b;
  }
};


//inde.js
var count=require('./calculator').count;
var add=require('./calculator').ADD;

console.log(count); // 0
add(2,3);
console.log(count); // 0

count +=1;
console.log(count); // 1

index.js中的count是对calculator.js中的count的一份拷贝,因此在调用ADD函数的时候,虽然改变了calculator.js中的count的值,但是并不会对index.js中导入时创建的副本造成影响。也就是说你在index.js中只要不是通过ADD函数对count的操作,都不会影响到calculator.js中的count。而是影响了副本的count。

require的模块路径可以动态指定,并支持传入一个表达式或者一个if进行判断是否加载模块。因此可以看出,在commonJS模块被执行前,并没有办法确定明确的依赖关系,模块的导入、导出发生在代码的运行阶段。

ES6 Module例子

//calculator.js
var count=0;
const ADD=function(a,b){
      count+=1;
      return a+b;
};
export {count,ADD}


//inde.html
<script type="module">
 import {count,ADD} from './src/calculator.js';
 console.log(count); // 0
 ADD(2,3);
 console.log(count); // 1
</script>

可以发现导入的变量其实是对原有值的动态映射。index.html中的count是对calculator.js中count值的实时反映,当我们调用ADD函数更改了calculator.js中count值时,index.html中的count的值也会随之变化。它不支持导入的路径是一个表达式,并且导入、导出语句必须位于模块的顶层作用域不能放到if语句中。因此ES6 Module是一个静态模块结构。

循环加载

“循环加载”表示存在强耦合,如果处理不好,还可能导致递归加载,使得程序无法执行,因此应该避免出现这种现象。

但是实际上,这是很难避免的,尤其是依赖关系复杂的大项目中很容易出现a依赖b,b依赖c,c又依赖a这样的情况。这意味着,模块加载机制必须考虑“循环加载”的情况。

对于JavaScript语言来说,目前最常见的两种模块格式CommonJS和ES6在处理“循环加载”时的方法是不一样的,返回的结果也不一样。

CommonJS的一个模块就是一个脚本文件。require命令第一次加载该脚本时就会执行整个脚本,然后在内存中生成一个对象。

ES6模块是动态引用,如果使用import从一个模块中加载变量(即import foo from ‘foo’),那么,变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者保证在真正取值的时候能够取到值。

一个简单的例子:

// a.js
import {bar} from './b.js';
export function foo() {
  console.log('foo');
  bar();
  console.log('执行完毕');
}
foo();

// b.js
import {foo} from './a.js';
export function bar() {
  console.log('bar');
  if (Math.random() > 0.5) {
    foo();
  }
}

按照CommonJS规范,上面的代码是无法执行的。a先加载b,然后b又加载a,这时a还没有任何执行结果,所以输出结果为null,即对于b.js来说,变量foo的值等于null,后面的foo()就会报错。

但是,ES6可以执行上面的代码。 

$ babel-node a.js
foo
bar
执行完毕

// 执行结果也有可能是
foo
bar
foo
bar
执行完毕
执行完毕

上面的代码中,a.js之所以能够执行,原因就在于ES6加载的变量都是动态引用其所在模块的。只要引用存在,代码就能执行。 

javascript模块化之ESM [toc]] 阅读详情

相关推荐

JavaScript中的AMD模块加载器详解

AMD模块加载器通过定义模块和依赖关系,实现了模块的异步加载和按需执行。当模块被使用时,AMD加载器会自动解析模块的依赖,并按照依赖的顺序加载和执行模块。在以上的示例中,我们使用require函数加载了moduleA模块,并在回调函数中使用了moduleA模块中的sayHello函数。在以上的示例中,我们定义了一个名为moduleA的模块,该模块的实现代码中定义了一个sayHello函数。按需加载:AMD模块加载器只在需要时加载模块,避免了不必要的模块加载,减少了资源的浪费。

XymkMl的博客 500

js 模块化:ESM ,CJS, AMD, UMD

一般来说,一个文件就是一个模块,这个文件内的作用域唯一,可以向外暴露变量,函数等。模块化的出现减少了代码的繁琐,利于代码复用和日后维等作用。JavaScript的模块系统有ESM ,CJS, AMD, UMD。

Y7998的博客 2789

从C-EPS到DP-EPS:手把手图解不同EPS类型怎么选,对你的车操控感影响有多大?

方向盘转动时那股细腻的阻尼感,高速过弯时令人安心的沉稳,或是狭窄车位里一根手指就能拨动的轻盈——这些看似微妙的差异,其实都源自转向系统电机那几厘米的安装位置变化。当我们谈论驾驶乐趣时,发动机参数和悬架调校总是占据C位,但真正连接驾驶者与车辆的神经末梢,恰恰是那套默默工作的电动助力转向系统(EPS)。不同EPS类型带来的操控特性差异,可能比马力数字更能定义一辆车的性格。

weixin_30920513的博客 531

JS模块化,ESM模块规范的 导入、导出、引用、调用详解

在之前的JS模块化的各种规范 之 CJS、AMD、CMD、UMD、ESM文章中,介绍了关于JS模块化的各种规范的区别和简单使用。由于ESM模块规范也是 ECMAScript2015(ES6)中的规范标准,在日常的Web项目开发、小程序开发、APP开发等都是很常用的,所以本文重点将 ESM模块规范中的 导出、导入、导出、引用、调用等,结合日常开发需求做进一步的介绍。

沐枫 4088

FPGA DMA IP核使用指南

数据传输:支持从源地址到目标地址的数据传输。中断管理:提供中断信号,便于CPU处理传输完成事件。传输控制:支持传输大小、方向和暂停/恢复控制。

weixin_66634995的博客 2428

Jetbrains IDE 配置上Gemini Code 插件,让你的的编程高效起飞~

Gemini Code Assist是 Google 家产品,基座模型为最新的Gemini 2.5 Pro。本篇实践了在 WebStrom 中Gemini Code Assist插件的高效编程。

2301_76993408的博客 4595

AMD CMD UMD CommonJs ESM 的历史和区别

在ESM出来之前,js是没有官方模块规范的。CommonJS凭借nodejs的知名度肯定是名气最大的。AMD CMD虽然都是大佬出的,但规范没法统一,这时候UMD出来解决了CommonJS、AMD、CMD的兼容统一问题。但ESM出来之后,这一切都将变成历史。总之,新代码用ESM就对了。

ScottePerk的博客 459

Ubuntu图形界面崩溃?从tty到GUI的终极修复指南

本文提供了Ubuntu图形界面崩溃后进入tty的终极修复指南。详细介绍了如何诊断显示管理器(如LightDM或GDM3)状态,并通过重装、切换显示管理器、修复依赖、系统升级及排查显卡驱动等核心方案,逐步恢复GUI。帮助用户从命令行界面高效修复桌面环境,避免数据丢失。

vulkan6gpu的博客 778

全面理解JS模块的标准(AMD、CMD、COMMON.JS 、 UMD、ESM)

require.js是AMD模块规范的一个具体实现核心是通过define方法对无序的代码进行有序的模块化定义,通过require方法实现代码的模块化加载});control.js/*** 登录状态检测*/};/*** 模块调用及配置*/{// 登录页});};// 注册页});};};{// 详情页});};};};});sea.js是CMD模块规范的一个具体实现在定义模块方面, CMD和AMD一样通过define函数来定义模块;

qq_30436011的博客 4837

达梦数据库JDBC连接池断开自动重连设置

一、场景 在网络状况不是非常良好,经常会出现暂时性的拥塞或者断开的情况,而且当我们重启数据库时也会发生类似的情况。所以需要配置中间件的连接池来实现连接测试以及自动重连,通过重新配置连接池,成功解决了这个问题。下面会给出一份数据源配置参数详单和一份推荐的数据源配置项。 二、连接池配置参数 1. initialSize:连接池启动时创建的初始化连接数量 2. maxActive:连接池中可同时连接的最大的连接数 3. maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负

lilv1989的博客 7237

ZYNQ BRAM实现PS与PL数据交互

有时CPU需要与PL进行小批量的数据交换,可以通过BRAM模块,也就是Block RAM实现此要求。本章通过Zynq的GP Master接口读写PL端的BRAM,实现与PL的交互。在本实验中加入了自定义的FPGA程序,并利用AXI4总线进行配置,通知其何时读写BRAM。以下为本实验原理图,CPU通过AXI BRAM Controller读取BRAM数据,CPU仅配置自定义的PL BRAM Controller 的寄存器,不通过它读写数据。

baidu_34971492的博客 2279

AMD+CMD+CommonJS+ESM的不同之处

AMD (RequireJS) AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMD AMD = Asynchronous Module Definition,即 异步模块定义。 AMD 规范加载模块是异步的,并允许函数回调,不必等到所有模块都加载完成,后续操作可以正常执行(依赖前置,提前执行)。 // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好

bigfatDone的博客 868

基于深度学习的柠檬等级检测系统 —— YOLOv8 + UI界面 + 数据集

本项目的目标是构建一个柠檬等级检测系统,通过深度学习模型自动检测柠檬的等级。自动检测柠檬等级:通过图像中的柠檬特征,自动判断其成熟度和质量。实时视频检测:通过摄像头实时监控柠檬的质量等级。用户友好的UI界面:为用户提供简洁直观的操作界面,支持图像上传、实时视频检测等功能。本项目展示了如何基于YOLOv8模型开发一个柠檬等级检测系统,结合PyQt5实现了用户友好的UI界面。通过该系统,用户可以快速上传柠檬图像并自动识别其等级,极大提升了检测效率和准确性。数据集的扩展。

YOLO 1112

前端JS 模块规范 CommonJS、CMD、AMD、ESM

CommonJS nodejs所采用的模块规范 导出模块:exports.myModule = function 或者 module.exports = {} 导入模块:var myModule = require("路径") CMD(Common Module Definition,通用模块定义) 引入模块加载器:&lt;script src="base/lib/sea.js" type="te...

qq_36873261的博客 1308

Python 安装 PyTorch(GPU)详细教程

本章教程,介绍如何安装PyTorch GPU版本的具体教程。

猿小白的博客 1625

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

一文搞懂 JavaScript 模块化规范:CommonJS、AMD、CMD、ES6 Module

CommonJS是一个规范,最初提出来是在浏览器以外的地方使用,并且当时被命名为ServerJS,后来为了体现它的广泛性,修改为CommonJS,也可简称为CJS。● Node是CommonJS在服务器端一个具有代表性的实现;● Browserify是CommonJS在浏览器中的一种实现;● Node中对CommonJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发,Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。

qq_44919431的博客 1595

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

JavaScript 模块化江湖:CommonJS、AMD、CMD、UMD 与 ESM 的终极对决

在JavaScript的模块化江湖里,CommonJS、AMD、CMD、UMD与ESM各自以不同的方式处理模块的定义和加载,上演了一场关于同步与异步、浏览器与服务器端适用性的终极对决,而ESM(ECMAScript Modules)作为官方标准,正逐渐统一这个纷争不断的领域

mutuyxy的博客 1196

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【JS】【前端】JavaScript 模块化演进之路(CJS/AMD/UMD/CMD/ESM)

JavaScript模块化演进经历了多个阶段:CommonJS(CJS)最早用于Node.js服务器端,采用同步加载和值拷贝;AMD为浏览器设计,支持异步加载;CMD强调就近依赖;UMD通过环境判断实现跨平台兼容;最终ES Modules(ESM)成为官方标准,支持静态加载和符号引用,实现浏览器与服务器统一。目前ESM已成为主流方案,取代了其他模块化规范

XPRNB的博客 1117

javascript/typescript模块那些事儿:commonJS和ES module

javascript模块最核心的写法

曲折旅程,艰难人生 1696

【无标题】

JS模块化

weixin_48146271的博客 109

AMD CMD CommonJS ESM UMD

require方法用于加载模块。相当于读入并执行一个js文件,然后返回该模块的exports对象 require命令用于加载文件,后缀名默认为.js 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了 node为每一个模块提供了一个exports变量(可以说是一个对象),指向 module.exports 不能把exports直接指向一个值,这样就相当于切断了 exports 和module.exports 的关系 导入机制,对于已导出的变量,不受原文件方法的印象 可以通过.on方法

海胆的博客 288

前端模块化汇总

模块化 含义 模块化: 模块化就是将单个文件当成一个模块,在日常项目开发里面我们不会将所有逻辑写在一个文件里面,不管是css还是js。原因是这样会导致单个文件过大,无法实现复用和维护,所以我们会将文件进行切割分离,这样分离独立出来的每一个文件都是一个模块。 css的模块化 在css里面,我们可以将单个公用的css文件进行分离,在需要的css文件里面导入。 原生css里面我们可以使用@import(css文件路径);进行导入。 sass/less/stylus都有各自的导入文件方法,例如s..

weixin_55305220的博客 328

JS模块化

module是一个 object ,保存着当前模块的信息,exports 是一个用于导出模块变量的对象,而 require 函数用于导入模块。而使用 require([依赖模块1,依赖模块2], function(){ }) 语法定义的模块,它的依赖模块会被打包成单独的一个 chunk 并且被异步加载。缺点:同步阻塞的模块加载方式,使得在浏览器加载大模块(或依赖大量模块)脚本文件时,加载过程就可能出现白屏,无响应等问题,用户体验很不好。和 AMD 一样,它的定义接口使用一个名为 define 的函数。

littlesamll的博客 440

前端模块化开发

前端模块化开发

qq_61880065的博客 2561

【js/css】CommonJS/AMD/CMD/UMD/ESM 模块化规范的区别

CommonJS 是同步的,只需要从项目文件夹读取就可以了,用时较短,但是浏览器端,需要从服务器端加载,如果js标签没有同步走完,页面假死,所以需要另外的方案,这就催生出AMD和CMD这些异步方案 AMD推崇依赖前置,基于RequireJS,在定义模块的时候就要声明其依赖的模块。 CMD推崇就近依赖,基于SeaJS,只有在用到某个模块的时候再去require。 UMD就是一种兼容 CommonJS/AMD/CMD 的兼容写法 ESM 设计思想是尽量的静态化,使得编译时就能确定模块的依..

当白的技术小窝 615

前端模块化规范

ESM 加载模块的方式同样取决于所处的环境,Node.js 同步加载,浏览器端异步加载。UMD 加载模块的方式取决于所处的环境,Node.js 同步加载,浏览器端异步加载。文件都是独立的模块,每个模块都有独立的作用域,模块里的本地变量都是私有的。规范下的代码不通用的问题,同时还支持将模块挂载到全局,是跨平台的解决方案。通过异步的方式加载模块,每加载一个模块实际就是加载对应的 JS 文件。通过异步的方式加载模块,每加载一个模块实际就是加载对应的 JS 文件。,降低学习使用成本,提高开发效率。

楠姐的博客 941
上一篇: nodejs-websocket简单实现多人聊天
下一篇: Docker、Dockerfile基本使用
大青花鱼の
博客等级 码龄8年 131粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值