http://www.planabc.net/2010/04/08/study_sandbox_pattern_in_yui3/
简化了一下 YUI3 中的沙箱实现 方式:
if (typeof Sandbox === 'undefined' || !Sandbox) {
Sandbox = function(o) {
var self = this;
if (!(self instanceof Sandbox)) { // 允许没有 new 操作符的实例化
return new Sandbox(o);
} else {
self._init();
self._config(o);
// 预加载某些指定模块
/* self._setup(); */
// 返回实例本身,支持链式模式
return self;
}
};
}
// Sandbox的(类)静态属性
Sandbox.Env = {
/* sidx: 0 , */
mods: {}
};
(function() {
var p, i,
SLICE = Array.prototype.slice,
/* instances = {}, */
time = new Date().getTime(),
win = window,
doc = document;
Sandbox.prototype = {
// 格式化配置参数
// NOTE:本着简单适用的原则,取消了原先 YUI 中对 loader 的支持
_config: function(o) {
var c = this.config, i, j, m, mods;
o = o || {};
// mods = c.modules;
for (i in o) {
if (i == 'win') {
c[i] = o[i].contentWindow || o[i];
c.doc = c[i].document;
} else {
c[i] = o[i];
}
}
},
/**
* 初始化沙箱实例
* @private
*/
_init: function() {
var self = this,
G_Env = Sandbox.Env,
Env = self.Env;
if(!Env) {
self.Env = {
mods: {},
_used: {},
_attached: {},
_loaded: {}
};
Env = self.Env;
/* if (G_Env && self !== Sandbox ) {
Env._sidx = ++ G_Env.sidx;
Env._guid = ('sandbox_' + Env._sidx + '_' + time).replace(/\./g, '_');
}
self.id = Env._guid;
instances[self.id] = self; */
}
self.constructor = Sandbox;
self.config = {
win: win || {},
doc: doc || {}
};
},
// 预留预加载某些指定模块,接口可根据实际需要扩展
/* _setup: function(o) {}, */
/**
* 添加模块
* @method add
* @param name {string} 模块名
* @param fn {Function} 模块对应的函数
* @param version {string}
* @param details 可选配置:
* requires - {array} 在本模块执行之前附加的必须的模块数组
* use - {array} 在本模块执行之后附加的模块数组
*
*/
add: function(name, fn, details) {
Sandbox.Env.mods[name] = {
name: name,
fn: fn,
details: details || {}
};
return this; // chain support
},
/**
* 执行与 Sandbox 实例相关联的模块:details.requires--》fn--》details.use
* @method _attach
* @param r {array} 模块列表数组
* @private
*/
_attach: function(r) {
var mods = Sandbox.Env.mods,
self = this,
attached = self.Env._attached,
i, l = r.length, name, m, fn, d, req, use;
for (i = 0; i < l; i = i+1) {
name = r[i];
m = mods[name];
if (!attached[name] && m) {
attached[name] = true;
fn = m.fn;
d = m.details;
req = d.requires;
use = d.use;
if (req) {
self._attach(req);
}
if (fn) {
fn(self);
}
if (use) {
self._attach(use);
}
}
}
},
/**
* 绑定模块至 Sandbox 实例
* @param modules* {string} 1-n 个模块 (uses arguments array)
* @param *callback {function} callback function 如果包括,必须是最后一个参数。
*
* Sandbox().use('planabc.net')
* Sandbox().use('planabc.net',function(){})
* Sandbox().use('planabc.net','planabc.com')
* Sandbox().use('planabc.net','planabc.com',function(){})
* Sandbox().use('*'); // use all available modules
*
*/
use: function() {
var self = this,
a = SLICE.call(arguments, 0),
mods = Sandbox.Env.mods,
used = self.Env._used,
loader,
firstArg = a[0],
callback = a[a.length-1],
k, i, l,
r = [],
process = function(name) {
// 添加模块至附加的模块列表
r.push(name);
// 一个模块仅附加一次
if (used[name]) {
return;
}
var m = mods[name], req, use, j, jl, t, tl,
d = m.details;
if (m) {
used[name] = true;
req = d.requires;
use = d.use;
}
// 附加上 requires 模块
if (req) {
for (j = 0,jl = req.length ; j < jl; j = j + 1) {
process(req[j]);
}
}
// 附加上 use 模块
if (use) {
for (t = 0, tl = use.length; t < tl; t = t + 1) {
process(use[t]);
}
}
},
onComplete;
if (typeof callback === 'function') {
a.pop();
} else {
callback = null;
}
onComplete = function() {
if (callback) {
callback(self);
}
};
// Sandbox().use('*');
if (firstArg === "*") {
a = [];
for (k in mods) {
if (mods.hasOwnProperty(k)) {
a.push(k);
}
}
if (callback) {
a.push(callback);
}
return self.use.apply(self, a);
}
l = a.length;
// 处理所有必须和附加的模块
for (i = 0; i < l; i = i + 1) {
process(a[i]);
}
self._attach(r);
onComplete();
return self; // chain support
}
};
})();