什么是AMD;什么是CMD
AMD
异步模块定义(AMD)API指定了一种定义模块的机制,以便可以异步加载模块及其依赖项。这特别适用于浏览器环境,其中模块的同步加载会导致性能,可用性,调试和跨域访问问题。
id
名字
第一个参数,id,是个字符串。它指的是定义中模块的名字,这个参数是可选的。如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。
模块名的格式
模块名用来唯一标识定义中模块,它们同样在依赖数组中使用。AMD的模块名规范是CommonJS模块名规范的超集。引用如下:
模块名是由一个或多个单词以正斜杠为分隔符拼接成的字符串
单词须为驼峰形式,或者".","…"
模块名不允许文件扩展名的形式,如".js"
模块名可以为 “相对的” 或 “顶级的”。如果首字符为".“或”…"则为"相对的"模块名
顶级的模块名从根命名空间的概念模块解析
相对的模块名从 “require” 书写和调用的模块解析
上文引用的CommonJS模块id属性常被用于JavaScript模块。
相对模块名解析示例:
如果模块 “a/b/c” 请求 “…/d”, 则解析为"a/d"
如果模块 “a/b/c” 请求 “./e”, 则解析为"a/b/e"
如果AMD的实现支持加载器插件(Loader-Plugins),则"!"符号用于分隔加载器插件模块名和插件资源名。由于插件资源名可以非常自由地命名,大多数字符都允许在插件资源名使用。
(译注:关于Loader-Plugins)
依赖
第二个参数,dependencies,是个定义中模块所依赖模块的数组。依赖模块必须根据模块的工厂方法优先级执行,并且执行的结果应该按照依赖数组中的位置顺序以参数的形式传入(定义中模块的)工厂方法中。
依赖的模块名如果是相对的,应该解析为相对定义中的模块。换句话来说,相对名解析为相对于模块的名字,并非相对于寻找该模块的名字的路径。
本规范定义了三种特殊的依赖关键字。如果"require",“exports”, 或 "module"出现在依赖列表中,参数应该按照CommonJS模块规范自由变量去解析。
依赖参数是可选的,如果忽略此参数,它应该默认为[“require”, “exports”, “module”]。然而,如果工厂方法的形参个数小于3,加载器会选择以函数指定的参数个数调用工厂方法。
工厂方法
第三个参数,factory,为模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
如果工厂方法返回一个值(对象,函数,或任意强制类型转换为true的值),应该为设置为模块的输出值。
简单的 CommonJS 转换
如果依赖性参数被忽略,模块加载器可以选择扫描工厂方法中的require语句以获得依赖性(字面量形为require(“module-id”))。第一个参数必须字面量为require从而使此机制正常工作。
在某些情况下,因为脚本大小的限制或函数不支持toString方法(Opera Mobile是已知的不支持函数的toString方法),模块加载器可以选择扫描不扫描依赖性。
如果有依赖参数,模块加载器不应该在工厂方法中扫描依赖性。
define.amd 属性
为了清晰的标识全局函数(为浏览器加载script必须的)遵从AMD编程接口,任何全局函数应该有一个"amd"的属性,它的值为一个对象。这样可以防止与现有的定义了define函数但不遵从AMD编程接口的代码相冲突。
当前,define.amd对象的属性没有包含在本规范中。实现本规范的作者,可以用它通知超出本规范编程接口基本实现的额外能力。
define.amd的存在表明函数遵循本规范。如果有另外一个版本的编程接口,那么应该定义另外一个属性,如define.amd2,表明实现只遵循该版本的编程接口。
一个如何定义同一个环境中允许多次加载同一个版本的模块的实现:
define.amd = {multiversion: true
};
最简短的定义:
define.amd = {};
一次输出多个模块
在一个脚本中可以使用多次define调用。这些define调用的顺序不应该是重要的。早一些的模块定义中所指定的依赖,可以在同一脚本中晚一些定义。模块加载器负责延迟加载未解决的依赖,直到全部脚本加载完毕,防止没必要的请求。
全局变量
本规范保留全局变量"define"以用来实现本规范。包额外信息异步定义编程接口是为将来的CommonJS API保留的。模块加载器不应在此函数添加额外的方法或属性。
本规范保留全局变量"require"被模块加载器使用。模块加载器可以在合适的情况下自由地使用该全局变量。它可以使用这个变量或添加任何属性以完成模块加载器的特定功能。它同样也可以选择完全不使用"require"。
使用注意
为了使静态分析工具(如build工具)可以正常工作,推荐使用字面上形如的’define(…)’。
与CommonJS的关系
一个关于本API的wiki开始在CommonJS wiki中创建了,作为中转的格式,模块中转。但是为了包含模块定义接口,随着时间而不断改变。在CommonJS列表中关于推荐本API作为模块定义API尚未达成一致。本API被转移到它自己的wiki和讨论组中。
AMD可以作为CommonJS模块一个中转的版本只要CommonJS没有被用来同步的require调用。使用同步require调用的CommonJS代码可以被转换为使用回调风格的AMD模块加载器。
**
CMD
**
在 Sea.js 中,所有 JavaScript 模块都遵循 CMD(Common Module Definition) 模块定义规范。该规范明确了模块的基本书写格式和基本交互规则。
在 CMD 规范中,一个模块就是一个文件
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
的书写需要遵循一些 简单约定。
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
一般用来加载可延迟异步加载的模块。
require.resolve
require.resolve(id)
使用模块系统内部的路径解析机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的绝对路径。
define(function(require, exports) {
console.log(require.resolve(’./b’));
// ==> http://example.com/path/to/b.js
});
这可以用来获取模块路径,一般用在插件环境或需动态拼接模块路径的场景下。
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() {}
};
});
如果
return
语句是模块中的唯一代码,还可简化为:
define({
foo: ‘bar’,
doSomething: function() {}
});
上面这种格式特别适合定义 JSONP 模块。
特别注意:下面这种写法是错误的!
define(function(require, exports) {
// 错误用法!!!
exports = {
foo: ‘bar’,
doSomething: function() {}
};
});
正确的写法是用
return
或者给
module.exports
赋值:
define(function(require, exports, module) {
// 正确写法
module.exports = {
foo: ‘bar’,
doSomething: function() {}
};
});
提示:
exports
仅仅是
module.exports
的一个引用。在
factory
内部给
exports
重新赋值时,并不会改变
module.exports
的值。因此给
exports
赋值是无效的,不能用来更改模块接口。
module
Object
module
是一个对象,上面存储了与当前模块相关联的一些属性和方法。
module.id
define(‘id’, [], function(require, exports, module) {
});
上面代码中,
define
的第一个参数就是模块标识。
module.uri
String
根据模块系统的路径解析规则得到的模块绝对路径。
define(function(require, exports, module) {
console.log(module.uri);
// ==> http://example.com/path/to/this/file.js
});
一般情况下(没有在
define
中手写
id
参数时),
module.id
的值就是
module.uri
,两者完全相同。
module.dependencies
Array
dependencies
是一个数组,表示当前模块的依赖。
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
});
注意:对
module.exports
的赋值需要同步执行,不能放在回调函数里。下面这样是不行的:
// x.js
define(function(require, exports, module) {
// 错误用法
setTimeout(function() {
module.exports = { a: “hello” };
}, 0);
});
在 y.js 里有调用到上面的 x.js:
// y.js
define(function(require, exports, module) {
var x = require(’./x’);
// 无法立刻得到模块 x 的属性 a
console.log(x.a); // undefined
});
小结
这就是 CMD 模块定义规范的所有内容。经常使用的 API 只有
define
,
require
,
require.async
,
exports
,
module.exports
这五个。其他
API 有个印象就好,在需要时再来查文档,不用刻意去记。
与 RequireJS 的 AMD 规范相比,CMD 规范尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。通过 CMD 规范书写的模块,可以很容易在 Node.js 中运行,
什么是AMD;什么是CMD相关推荐
- JavaSript模块规范 - AMD规范与CMD规范介绍[转]
原文地址:http://blog.chinaunix.net/uid-26672038-id-4112229.html JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什 ...
- JavaSript模块化 AMD CMD 详解.....
模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理.模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式.可以想象一个巨大 ...
- CommonJS/AMD/CMD/UMD
为什么会有这几种模式? 起源:Javascript模块化 模块化就是把复杂问题分解成不同模块,这样可维护性高,从而达到高复用,低耦合. 1.Commonjs CommonJS是服务器端模块的规范,No ...
- AMD和CMD出生的背景和它们解决的问题
这是一篇纯故事没有代码的博客,毕竟ES6官方标准规定了模块化,这两位民间出生的规范就差点意思了,所以也不再详细介绍它俩了. 我们知道CommonJS的工作原理是:当使用require(模块路径)导入一 ...
- CommonJS,AMD,CMD区别 - 郑星阳 - ITeye博客
CommonJS,AMD,CMD区别 博客分类: seajs和requirejs JavaScript zccst转载 学得比较晕,再次看commonjs,amd, cmd时好像还是没完全弄清楚,今天 ...
- js模块化编程之彻底弄懂CommonJS和AMD/CMD!
为什么80%的码农都做不了架构师?>>> 先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块. 但是,这样做有一个前 ...
- js模块化编程之彻底弄懂CommonJS和AMD/CMD
转载地址:http://www.cnblogs.com/chenguangliang/p/5856701.html 先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想 ...
- 兼容多种模块规范(AMD,CMD,Node)的代码
前言 昨天,公司同事问了我如下一个问题: 说他在看一个插件时,看到了源码结构如截图所示,他知道(function(){})()是一种立即执行函数,但是在截图中,最后的那个圆括号里又写了一个函数func ...
- 模块化 AMD与CMD 规范
JavaSript模块规范 - AMD规范与CMD规范介绍 2014-02-19 13:12:01 分类: JavaScript JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单 ...
- AMD, CMD, CommonJS和UMD
AMD, CMD, CommonJS和UMD 今天由于项目中引入的echarts的文件太大,requirejs经常加载超时,不得不分开来加载echarts的各个图表.但是使用echarts自带的在线构 ...
最新文章
- Python 技术篇-基于随机数的uuid码的生成
- rop检查_注意!这几类人一定要定期检查眼底!
- 28 Java类的加载机制、什么是类的加载、类的生命周期、加载:查找并加载类的二进制数据、连接、初始化、类加载器、双亲委派模型、自定义类加载器
- 递推与储存,是动态规划的关键
- zabbix专题:第六章 动作Actions、告警方式Medias
- Tensorflow 搭建自己的神经网络(四)
- 指尖下的js —— 多触式web前端开发之三:处理复杂手势
- 深入理解原型和原型链
- 怎样在Word2010中新建样式
- Easyx-----c语言实现图形化打砖块
- php网站做分享到朋友圈,PHP实现微信分享朋友圈
- 淮安万达机器人_淮安万博机器人 万达上班时间【输入网址YB7888.vip】angmi_PP视频搜索-PP视频-原PPTV聚力视频...
- rm -rf 命令 与正则表达式
- 微观结构到应用材料力学行为
- 知网caj文件转pdf(无需下载任何软件,傻瓜式操作,必看!!!)
- JAVA中native方法(实现例子)
- mssql和mysql注入区别_Mssql手工注入小结
- !QQ陌生人通过“它”可以和你临时会话!
- AP计算机A自学笔记:程序分析
- 二战 北航 浙大 计算机,二战北航,成功上岸,分享经验给大家