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

String
模块的唯一标识。

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相关推荐

  1. JavaSript模块规范 - AMD规范与CMD规范介绍[转]

    原文地址:http://blog.chinaunix.net/uid-26672038-id-4112229.html JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什 ...

  2. JavaSript模块化 AMD CMD 详解.....

    模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理.模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式.可以想象一个巨大 ...

  3. CommonJS/AMD/CMD/UMD

    为什么会有这几种模式? 起源:Javascript模块化 模块化就是把复杂问题分解成不同模块,这样可维护性高,从而达到高复用,低耦合. 1.Commonjs CommonJS是服务器端模块的规范,No ...

  4. AMD和CMD出生的背景和它们解决的问题

    这是一篇纯故事没有代码的博客,毕竟ES6官方标准规定了模块化,这两位民间出生的规范就差点意思了,所以也不再详细介绍它俩了. 我们知道CommonJS的工作原理是:当使用require(模块路径)导入一 ...

  5. CommonJS,AMD,CMD区别 - 郑星阳 - ITeye博客

    CommonJS,AMD,CMD区别 博客分类: seajs和requirejs JavaScript zccst转载 学得比较晕,再次看commonjs,amd, cmd时好像还是没完全弄清楚,今天 ...

  6. js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    为什么80%的码农都做不了架构师?>>>    先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块. 但是,这样做有一个前 ...

  7. js模块化编程之彻底弄懂CommonJS和AMD/CMD

    转载地址:http://www.cnblogs.com/chenguangliang/p/5856701.html 先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想 ...

  8. 兼容多种模块规范(AMD,CMD,Node)的代码

    前言 昨天,公司同事问了我如下一个问题: 说他在看一个插件时,看到了源码结构如截图所示,他知道(function(){})()是一种立即执行函数,但是在截图中,最后的那个圆括号里又写了一个函数func ...

  9. 模块化 AMD与CMD 规范

    JavaSript模块规范 - AMD规范与CMD规范介绍 2014-02-19 13:12:01 分类: JavaScript JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单 ...

  10. AMD, CMD, CommonJS和UMD

    AMD, CMD, CommonJS和UMD 今天由于项目中引入的echarts的文件太大,requirejs经常加载超时,不得不分开来加载echarts的各个图表.但是使用echarts自带的在线构 ...

最新文章

  1. Python 技术篇-基于随机数的uuid码的生成
  2. rop检查_注意!这几类人一定要定期检查眼底!
  3. 28 Java类的加载机制、什么是类的加载、类的生命周期、加载:查找并加载类的二进制数据、连接、初始化、类加载器、双亲委派模型、自定义类加载器
  4. 递推与储存,是动态规划的关键
  5. zabbix专题:第六章 动作Actions、告警方式Medias
  6. Tensorflow 搭建自己的神经网络(四)
  7. 指尖下的js —— 多触式web前端开发之三:处理复杂手势
  8. 深入理解原型和原型链
  9. 怎样在Word2010中新建样式
  10. Easyx-----c语言实现图形化打砖块
  11. php网站做分享到朋友圈,PHP实现微信分享朋友圈
  12. 淮安万达机器人_淮安万博机器人 万达上班时间【输入网址YB7888.vip】angmi_PP视频搜索-PP视频-原PPTV聚力视频...
  13. rm -rf 命令 与正则表达式
  14. 微观结构到应用材料力学行为
  15. 知网caj文件转pdf(无需下载任何软件,傻瓜式操作,必看!!!)
  16. JAVA中native方法(实现例子)
  17. mssql和mysql注入区别_Mssql手工注入小结
  18. !QQ陌生人通过“它”可以和你临时会话!
  19. AP计算机A自学笔记:程序分析
  20. 二战 北航 浙大 计算机,二战北航,成功上岸,分享经验给大家

热门文章

  1. 【人工智能】深度学习、神经网络图
  2. 心电图心电轴怎么计算_心电图心电轴计算表
  3. 跳过基于AMD平台安装ESXI 6.7,并部署win10和黑群辉虚拟机的坑
  4. 如何修改vant组件中filed的placeholder的 颜色
  5. 考出PMP证书到底有没有用?
  6. 案例:WLC HA主WLC进入维护模式
  7. java游戏服务器面试_服务器 面试
  8. 笔记本电脑数字键盘打不出数字的解决方案
  9. 在Kotlin中@Suppress可能取到的值
  10. Qt撤销回/撤框架:QUndoCommand