装饰者(Decorator)模式:1
// mylib/UpdatableObservable:dojo/store/Observable 的一个装饰者
define(['dojo', 'dojo/store/Observable'], function ( dojo, Observable ) {
return function UpdatableObservable ( store ) {
var observable = dojo.isFunction(store.notify) ? store :new Observable(store);
observable.updated = function( object ) {
dojo.when(object, function ( itemOrArray ) {
dojo.forEach( [].concat(itemOrArray), this.notify, this );
};
};
return observable; // 让 `new` 成为可选的
};
});
1 | // 装饰者使用者// mylib/UpdatableObservable 的一个使用者 define(['mylib/UpdatableObservable'], function ( makeUpdatable ) { var observable, updatable, someItem; // ... 获取或得到 `observable` 的代码 // ... 让 observable store 也变得 updatable updatable = makeUpdatable(observable); // `new` is optional! // ... 之后,当一条 cometd 消息带着新的数据项到达时 updatable.updated(updatedItem); }); |
适配器(Adapter)模式1
// 'mylib/Array' 将 `each` 函数适配为仿 jQuery 的接口:
define(['dojo/_base/lang', 'dojo/_base/array'], function (lang, array) {
return lang.delegate(array, {
each: function (arr, lambda) {
array.forEach(arr, function (item, i) {
lambda.call(item, i, item); // 就像 jQuery 的 each
})
}
});
});
// 适配器使用者
// 'myapp/my-module':
define(['mylib/Array'], function ( array ) {
array.each(['uno', 'dos', 'tres'], function (i, esp) {
// 这里 `this` == item
});
});
1 | define(['js/jquery.js','js/jquery.color.js','js/underscore.js'], function($, colorPlugin, _){ // 这里我们传入了 jQuery、color 插件以及 Underscore // 我们在全局作用域中无法访问其中的任何一个,但我们可以轻易地在 // 伪随机生成一个颜色数组,选中打乱后数组中的第一项 var shuffleColor = _.first(_.shuffle(['#666','#333','#111'])); // 给页面中任意 class 带有 'item' 的元素用随机得到的颜色为 // background-color 添加动画效果 $('.item').animate({'backgroundColor': shuffleColor }); return {}; // 我们返回的东西可以被其它模块所使用 }); |
1 | // 让文档中存在多个 jQuery 的全局实例,以便测试 .noConflict() var jQuery = this.jQuery || "jQuery", $ = this.$ || "$", originaljQuery = jQuery, original$ = $, amdDefined; define(['jquery'] , function ($) { $('.items').css('background','green'); return function () {}; }); // 易实现的声明支持的标志,会被 AMD 加载器所使用 define.amd = { jQuery: true }; |
理解 CJS:require() 与 exports// package/lib 是我们须要的一个依赖项
var lib = require(‘package/lib’);
// 我们的模块的一些行为
function foo(){
lib.log(‘hello world!’);
}
// 把 foo 导出(暴露)给其它模块
exports.foo = foo;
exports 的基本用法// 定义我们希望暴露的更多行为function foobar(){
this.foo = function(){
console.log(‘Hello foo’);
}
this.bar = function(){
console.log('Hello bar');
}
}
// 把 foobar 暴露给其它模块
exports.foobar = foobar;
// 一个使用了 ‘foobar’ 的应用
// 相对于使用文件与模块文件所在的同一目录路径获取模块
var foobar = require(‘./foobar’).foobar,
test = new foobar();
test.bar(); // ‘Hello bar’1
第一个 CJS 例子的 AMD 等价写法
```dash
define(['package/lib'], function(lib){
// 我们的模块的一些行为
function foo(){
lib.log('hello world!');
}
// 把 foo 导出(暴露)给其它模块
return {
foobar: foo
};
});
`
使用多个依赖项app.js
var modA = require(‘./foo’);
var modB = require(‘./bar’);
exports.app = function(){
console.log(‘Im an application!’);
}
exports.foo = function(){
return modA.helloWorld();
}
bar.js
exports.name = ‘bar’;
foo.jsrequire(‘./bar’);
exports.helloWorld = function(){
return ‘Hello World!!’’
}1
AMD/CommonJS 通用模块定义(变体 2,UMDjs)/**
* 如果你需要做一些循环依赖或是需要兼容非 Node 的类
* commonjs 环境,导出基于对象的版本。
*/
```dash
(function (define) {
//'id' 是可选的,但如果这是一个流行的 web 类库而且
//通常被用于非 AMD/Node 的环境下,还是推荐给出。然
//而如果希望生成匿名模块,去掉下面的 'id',并且去掉
//define 兼容方案中使用的 id。
define('id', function (require, exports) {
//如果有兼容项,把它们加载进来
var a = require('a');
//给 exports 绑定属性。
exports.name = value;
});
}(typeof define === 'function' && define.amd ? define : function (id, factory) {
if (typeof exports !== 'undefined') {
//commonjs
factory(require, exports);
} else {
//创建一个全局函数。仅在代码没有依赖项、或
//是依赖项符合下面的调用模式时可用。
factory(function(value) {
return window[value];
}, (window[id] = {}));
}
}));
可扩展的 UMD 插件(Thomas Davis 和我自己修改的变体)core.js1
;(function ( name, definition ){
var theModule = definition(),
// 这被认为是“安全”的:
hasDefine = typeof define === 'function' && define.amd,
// hasDefine = typeof define === 'function',
hasExports = typeof module !== 'undefined' && module.exports;
if ( hasDefine ){ // AMD 模块
define(theModule);
} else if ( hasExports ) { // Node.js 模块
module.exports = theModule;
} else { // 分配到常见的命名空间,或简单地分配到全局对象(window)
(this.jQuery || this.ender || this.$ || this)[name] = theModule;
}
})( 'core', function () {
var module = this;
module.plugins = [];
module.highlightColor = "yellow";
module.errorColor = "red";
// 在这里定义 core 模块并返回公用 API
// 这是 core 的方法 highlightAll() 和所有插件使用的 highlight 方法
// 用来把元素高亮显示为不同颜色
module.highlight = function(el,strColor){
// 这个模块使用了 jQuery,但是老式的普通 JavaScript 或者 Dojo
// 也可以很简单地使用。
if(this.jQuery){
jQuery(el).css('background', strColor);
}
}
return {
highlightAll:function(){
module.highlight('div', module.highlightColor);
}
};
});
myExtension.js
;(function ( name, definition ) {
var theModule = definition(),
hasDefine = typeof define === 'function',
hasExports = typeof module !== 'undefined' && module.exports;
if ( hasDefine ) { // AMD 模块
define(theModule);
} else if ( hasExports ) { // Node.js 模块
module.exports = theModule;
} else { // // 分配到常见的命名空间,或简单地分配到全局对象(window)
// for 循环用来处理扁平文件/全局模块扩展名
var obj = null;
var namespaces = name.split(".");
var scope = (this.jQuery || this.ender || this.$ || this);
for (var i = 0; i < namespaces.length; i++) {
var packageName = namespaces[i];
if (obj && i == namespaces.length - 1) {
obj[packageName] = theModule;
} else if (typeof scope[packageName] === "undefined") {
scope[packageName] = {};
}
obj = scope[packageName];
}
}
})('core.plugin', function () {
// 在这里定义你的模块并返回公用 API
// 这段代码可以轻易地与 core 代码相适应,来允许那些覆盖/扩展 core
// 功能的方法,让你在需要时扩展 highlight 方法来做更多事。
return {
setGreen: function ( el ) {
highlight(el, 'green');
},
setRed: function ( el ) {
highlight(el, errorColor);
}
};
});
//app.js
$(function(){
// 'core' 插件在本例中被暴露在了一个命名空间 core 下,我们
// 先将它缓存起来
var core = $.core;
// 然后使用一些原生的 core 功能来用黄色高亮页面中所有的 div
core.highlightAll();
// 访问被载入 core 模块的 'plugin' 命名空间的插件(扩展):
// 把页面中的第一个 div 设为绿色背景。
core.plugin.setGreen("div:first");
// 这里我们通过一个在其之后加载的插件从底层使用 core 的 'highlight' 方法
// 把最后一个 div 的背景色设为我们在 core 模块/插件中定义的
// 'errorColor' 属性的颜色。如果你更仔细地查看代码,就会发现
// 在 core 和其它插件间使用属性和方法是多么简单
core.plugin.setRed('div:last');
});
1 | module staff{ // 指定其它模块可以使用的(公用)导出 export var baker = { bake: function( item ){ console.log('Woo! I just baked ' + item); } } } module skills{ export var specialty = "baking"; export var experience = "5 years"; } module cakeFactory{ // 指定依赖项 import baker from staff; // 通过通配符导入所有东西 import * from skills; export var oven = { makeCupcake: function( toppings ){ baker.bake('cupcake', toppings); }, makeMuffin: function( mSize ){ baker.bake('muffin', size); } } } |
针对服务器的类 CommonJS 模块对于面向服务器的开发者来说,在 ES.next 中提出的模块系统并非局限于对浏览器端模块的关注。通过下面的例子,你可以看见一个被提出用于服务器的类 CJS 模块:1
// io/File.js
export function open(path) { ... };
export function close(hnd) { ... };
// compiler/LexicalHandler.jsmodule file from 'io/File';
import { open, close } from file;
export function scan(in) {
try {
var h = open(in) ...
}
finally { close(h) }
}
module lexer from 'compiler/LexicalHandler';
module stdlib from '@std';