JS之AMD、CMD、CommonJS、ES6、UMD的使用笔记
前言
如下图:

AMD与CMD的主要区别:
- 1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
- 2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
var b = require('./b')
b.doSomething()
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
b.doSomething()
})
AMD与CMD的其它区别可参考地址:https://www.zhihu.com/question/20351507
AMD
AMD规范可参考地址:https://github.com/amdjs/amdjs-api/wiki/AMD
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
根据AMD规范,我们可以使用define定义模块,使用require调用模块,语法:
define(id?, dependencies?, factory);
- id: 定义中模块的名字;可选;如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字;
- dependencies:依赖的模块;
- factory:工厂方法,返回定义模块的输出值。
总结一段话:声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行,依赖前置
例子1:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
return require("beta").verb();
}
});
例子2:
define(["alpha"], function (alpha) {
return {
verb: function(){
return alpha.verb() + 2;
}
};
});
例子3:
define({
add: function(x, y){
return x + y;
}
});
例子4:
define(function (require, exports, module) {
var a = require('a'),
b = require('b');
exports.action = function () {};
});
使用require函数加载模块:
require([dependencies],function(){});
- 第一个参数是一个数组,表示所依赖的模块
- 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用.加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块
require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题
require(['alpha'],function(alpha){
alpha.verb ();
})
CMD
CMD规范参考地址:https://github.com/seajs/seajs/issues/242 CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
define Function
define 是一个全局函数,用来定义模块。
define define(factory)
define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串。
factory 为对象、字符串时,表示模块的接口就是该对象、字符串。比如可以如下定义一个 JSON 数据模块:
define({ "foo": "bar" });
也可以通过字符串定义模板模块:
define('I am a template. My name is {{name}}.');
factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:require、exports 和 module:
define(function(require, exports, module) {
// 模块代码
});
define define(id?, deps?, factory)
define 也可以接受两个以上参数。字符串 id 表示模块标识,数组 deps 是模块依赖。比如:
define('hello', ['jquery'], function(require, exports, module) {
// 模块代码
});
id 和 deps 参数可以省略。省略时,可以通过构建工具自动生成。
注意:带 id 和 deps 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。
define.cmd Object
一个空对象,可用来判定当前页面是否有 CMD 模块加载器:
if (typeof define === "function" && define.cmd) {
// 有 Sea.js 等 CMD 模块加载器存在
}
require Function
require 是 factory 函数的第一个参数。
require require(id)
require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口。
define(function(require, exports) {
// 获取模块 a 的接口
var a = require('./a');
// 调用模块 a 的方法
a.doSomething();
});
require.async require.async(id, callback?)
require.async 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback 参数可选。
define(function(require, exports, module) {
// 异步加载一个模块,在加载完成时,执行回调
require.async('./b', function(b) {
b.doSomething();
});
// 异步加载多个模块,在加载完成时,执行回调
require.async(['./c', './d'], function(c, d) {
c.doSomething();
d.doSomething();
});
});
注意:require 是同步往下执行,require.async 则是异步回调执行。require.async 一般用来加载可延迟异步加载的模块。
exports Object
exports 是一个对象,用来向外提供模块接口。
define(function(require, exports) {
// 对外提供 foo 属性
exports.foo = 'bar';
// 对外提供 doSomething 方法
exports.doSomething = function() {};
});
除了给 exports 对象增加成员,还可以使用 return 直接向外提供接口。
define(function(require) {
// 通过 return 直接提供接口
return {
foo: 'bar',
doSomething: function() {}
};
});
module Object
module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
module.id String
模块的唯一标识。
define('id', [], function(require, exports, module) {
// 模块代码
});
上面代码中,define 的第一个参数就是模块标识。
module.exports Object
当前模块对外提供的接口。
传给 factory 构造方法的 exports 参数是 module.exports 对象的一个引用。只通过 exports 参数来提供接口,有时无法满足开发者的所有需求。 比如当模块的接口是某个类的实例时,需要通过 module.exports 来实现:
define(function(require, exports, module) {
// exports 是 module.exports 的一个引用
console.log(module.exports === exports); // true
// 重新给 module.exports 赋值
module.exports = new SomeClass();
// exports 不再等于 module.exports
console.log(module.exports === exports); // false
});
CommonJS
CommonJS是服务器端模块的规范,Node.js采用了这个规范.Node.JS首先采用了js模块化的概念.
CommonJS定义的模块分为:模块引用(require)/ 模块定义(exports)/模块标识(module)
所有代码都运行在模块作用域,不会污染全局作用域。
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
模块加载的顺序,按照其在代码中出现的顺序。
//common.js
module.exports = function(a, b) {
return a-b
} let minus = require('./common.js') //文件相对路径
console.log(minus(5,4))
// 结果: 1
详细可以参考《阮一峰:CommonJS规范》
ES6
导出
ES6两种导出方式:
- 命名导出
- 默认导出
命名导出
// 写法1
export const name = 'calculator';
export const add = function (a,b) {
return a + b;
} // 写法2
const name = 'calculator';
const add = function (a,b) {
return a + b;
}
export {name, add};
在使用命名导出时,可以通过as关键字对变量重命名。如:
const name = 'calculator';
const add = function (a,b) {
return a + b;
}
export {name, add as getSum}; // 在导入时即为name 和 getSum
默认导出
export default {
name: 'calculator';,
add: function (a,b) {
return a + b;
}
};
导入
针对命名导出的模块,导入方式如下:
// calculator.js
const name = 'calculator';
const add = function (a,b) {
return a + b;
}
export {name, add}; // 一般导入方式
import {name, add} from './calculator.js'
add(2,3); // 通过as关键字对导入的变量重命名
import {name, add as calculateSum} from './calculator.js'
calculateSum(2,3); // 使用 import * as <myModule>可以把所有导入的变量作为属性值添加到<myModule>对象中,从而减少了对当前作用域的影响
import * as calculateObj from './calculator.js'
calculateObj.add(2,3);
对于默认导出来说,import后面直接跟变量名,并且这个名字可以自由指定,它指代了calculator.js中默认导出的值。从原理上可以这样理解:
import {default as myCalculator} from './calculator.js'
还有两种导入方式混合起来使用的例子,如下:
// index.js
import React, {Component} from 'react';
注:这里的React必须写在大括号前面,而不能顺序颠倒,否则会提示语法错误。
复合写法
在工程中,有时候需要把一个模块导入后立即导出,比如专门用来集合所有页面或组件的入口文件。此时可以采用复合形式的写法:
export {name, add } from './calculator.js'
复合写法只支持通过命名导出的方式暴露出来的变量,默认导出则没有对应的复合形式,只能将导入和导出拆分开。
import calculator from './calculator.js'
export default calculator;
UMD
UMD并不能说是一种模块标准,不如说它是一组模块形式的集合更准确。UMD的全称是Universal Module Definition,也就是通用模块标准。它的目标是使一个模块能运行在各种环境下,不论是CommonJS、AMD,还是非模块化的环境(当时ES6 Module还未被提出)
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之类的
module.exports = factory(require('jquery'));
} else {
// 浏览器全局变量(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function($) {
// 方法
function myFunc() {};
// 暴露公共方法
return myFunc;
}));
详细可参考:《可能是最详细的UMD模块入门指南》、《AMD , CMD, CommonJS,ES Module,UMD》
JS之AMD、CMD、CommonJS、ES6、UMD的使用笔记的更多相关文章
- FW: AMD, CMD, CommonJS和UMD
javascript 我是豆腐不是渣 4月5日发布 推荐 2 推荐 收藏 32 收藏,486 浏览 今天由于项目中引入的echarts的文件太大,requirejs经常加载超时,不得不分开来加载ech ...
- AMD, CMD, CommonJS和UMD
我的Github(https://github.com/tonyzheng1990/tonyzheng1990.github.io/issues),欢迎star 今天由于项目中引入的echarts的文 ...
- js模块系统 - amd|cmd|commonjs|esm|umd
写过前端代码大概率听说过amd cmd umd commonjs esm这些名词, 想当初我第一次看到这些的时候, 人都麻了, 都是些啥啊. 后来我知道了, 这些都是js的模块规范. amd - 浏览 ...
- JS模块之AMD, CMD, CommonJS、UMD和ES6模块
CommonJS 传送门 同步加载,适合服务器开发,node实现了commonJS.module.exports和require 判断commonJS环境的方式是(参考jquery源码): if ( ...
- AMD,CMD.CommonJs和UMD还有es6的模块化对比
CommonJS CommonJS是服务器端模块的规范,Node.js采用了这个规范. 根据CommonJS规范,一个单独的文件就是一个模块.加载模块使用require方法,该方法读取一个文件并执行, ...
- AMD CMD commonJS es6
看到很多人傻傻的分不清楚 AMD.CMD . commonJS . es6的区别,实际上这跟这几年前段技术的发展有很大的关系. 实际上这是JavaScript的模块化思想演进的一个过程. 最开始的时候 ...
- es6的模块化--AMD/CMD/commonJS/ES6
, ); ); }) , )); }); , )); ; export { firstName, lastName, year }; // es6引用 import { firstName, last ...
- Amd,Cmd, Commonjs, ES6 import/export的异同点
Amd,Cmd, Commonjs, ES6 import/export等均是模块化方案 1.Commonjs使用在Nodejs上,加载模块是同步的. 2.Amd是requirejs在推广过程中对模块 ...
- AMD/CMD/CommonJs到底是什么?它们有什么区别?
知识点1:AMD/CMD/CommonJs是JS模块化开发的标准,目前对应的实现是RequireJs/SeaJs/nodeJs. 知识点2:CommonJs主要针对服务端,AMD/CMD主要针对浏 ...
- js模块化AMD/CMD
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统 ...
随机推荐
- Navicat for mysql 无法连接到虚拟机的linux系统下的mysql
最近在linux Centos7版本的虚拟机上安装了一个MySql数据库,发现本地可以正常ping通虚拟机,但Navicat则无法正常连接到虚拟机里的MySql数据库,经过一番琢磨,发现解决这个问题的 ...
- 屏幕分辨率基础概念PX,PT,DP,DPR,DPI说明
屏幕分辨率基础概念说明 缩写 全称 说明 PX Device Pixels 设备像素,指设备的物理像素 PX CSS Pixels CSS像素,指CSS样式代码中使用的逻辑像素 DOT Dot 点,屏 ...
- AT_agc019_b 题解
洛谷链接&Atcoder 链接. 题目简述 给定一个字符串 \(A\),可以选择区间 \([i,j]\) 翻转一次,求能得到多少本质不同的字符串.(\(A\) 的长度不超过 \(2 \time ...
- [rCore学习笔记 013]GDB跟踪程序
题目要求 请学习 gdb 调试工具的使用(这对后续调试很重要),并通过 gdb 简单跟踪从机器加电到跳转到 0x80200000 的简单过程.只需要描述重要的跳转即可,只需要描述在 qemu 上的情况 ...
- Cython与C函数的结合
技术背景 在前面一篇博客中,我们介绍了使用Cython加速谐振势计算的方法.有了Cython对于计算过程更加灵活的配置(本质上是时间占用和空间占用的一种均衡),及其接近于C的性能,并且还最大程度上的保 ...
- 巧用 QLineF 从 QTransform 提取角度
我们在对 QGraphicsItem 进行变换时,QT 提供了很多便捷的方法.但当我们想获取当前变换的角度时却有些困难,因为 QTransform 没有提供获取角度的方法.在文章Qt 从 QTrans ...
- 【Java】Annotation 注解
Annotation 注解 注解是一种元数据 MetaData,从JDK5开始 在Java代码中是一个特殊的标记,可以在编译,类加载,运行时读取,执行对应的处理 程序可以在不改变原有逻辑的基础上嵌入一 ...
- 【DataBase】MySQL 07 SQL函数 单行函数其一 字符函数
SQL函数的概念 -- SQL函数 -- 概念:类似Java的方法,将已经定义好的不再改变的逻辑语句封装在函数体内,对外提供方法的标识 -- 隐藏了实现细节,提高功能的可重用 -- SELECT 函数 ...
- 《Python数据可视化之matplotlib实践》 源码 第三篇 演练 第九章
图 9.1 import matplotlib.pyplot as plt import numpy as np fig=plt.figure() ax=fig.add_subplot(111) f ...
- 台式机电脑散热之狂想曲——主机机箱散热的另类方法(纯空想中ing)
本博文是一篇狂想曲,之所以叫狂想曲是因为本文只是博主在无聊时突发奇想,而且仅停留于想的阶段,所以本文内容不用太过认真. 事情是这样的,博主有一台式机,有事没事的就喜欢宅在宿舍里面,有时候还能偶然用这台 ...