javascript実現モジュール搭載器
6431 ワード
構想を実現するのはネット上の資料から来て、自分でいくつか改正をして、学習だけに供えます.
window.ISF = (function(win, doc) {
Array.prototype.remove = function() {
var items = arguments,
k = 0,
len = items.length,
item = null;
for (; k < len; k++) {
item = items[k];
for (var i = 0, n = 0; i < this.length; i++) {
if (this[i] != item) {
this[n++] = this[i];
}
}
this.length = n;
}
return this;
};
var moduleCache = {},
head = doc.head;
function Mod(config){
this.handlers = {};
this.oneTimeHandlers = {};
this.modName = config.modName;
this.status = config.status;
this.export = config.export;
this.on = function(type, handler){
this.handlers[type] = this.handlers[type] || [];
this.handlers[type].push(handler);
return this;
};
this.off = function(type, handler){
if(this.handlers[type]){
this.handlers[type].remove(handler);
}
if(this.oneTimeHandlers[type]){
this.oneTimeHandlers[type].remove(handler);
}
return this;
};
this.one = function(type, handler){
this.oneTimeHandlers[type] = this.oneTimeHandlers[type] || [];
this.oneTimeHandlers[type].push(handler);
return this;
};
this.fire = function(){
var eventResults = [],
type = arguments[0],
args = Array.prototype.slice.call(arguments, 1),
_handlers = this.handlers[type],
_oneTimeHandlers = this.oneTimeHandlers[type],
_oneTimeHandlersLen = _oneTimeHandlers.length;
if(_handlers && _handlers.length > 0){
for(var i = 0, len = _handlers.length; i < len; i++){
eventResults.push(_handlers[i].apply(this, args));
}
}
if(_oneTimeHandlers && _oneTimeHandlersLen> 0){
for(var i = 0; i < _oneTimeHandlersLen; i++){
eventResults.push(_oneTimeHandlers[i].apply(this, args));
}
}
_oneTimeHandlers=[];
return eventResults.length == 1 ? eventResults[0] : eventResults;
};
}
var createScript = function(url,onload) {
var _script = document.createElement('script');
_script.type = 'text/javascript';
_script.charset = 'utf-8';
_script.async = true;
_script.src = url;
if(onload){
_script.onload = function(){
onload();
};
}
var firstScript = document.getElementsByTagName('script')[0];
if(firstScript){
firstScript.parentNode.insertBefore(_script, firstScript);
}else{
head.appendChild(_script);
}
};
var loadMod = function(modName, callback) {
var mod = moduleCache[modName];
if(mod){
if(mod.status == 'loaded'){
setTimeout(callback(mod.export), 0);
}else{
mod.one('loaded', callback);
}
}else{
mod = moduleCache[modName] = new Mod({
modName : modName,
status : 'loading',
export : null
});
mod.one('loaded', callback);
createScript(modName + ".js");
}
};
var saveModule = function(modName, params, factory){
console.log('modName='+modName);
var _export = (typeof factory == 'function') ? factory.apply(null, params) : factory;
if(modName){
var mod = moduleCache[modName];
mod.status = 'loaded';
mod.export = _export;
mod.fire('loaded', mod.export);
}
};
var ISF = {
loadModule : function(modName, factory, config) {
config = config ||{};
var requires = config.requires;
if (requires && requires.length) {
var params = [],
depCount = 0;
for (i = 0, len = requires.length; i < len; i++) {
(function(i) {
// 1
depCount++;
loadMod(requires[i], function(param) {
params[i] = param;
depCount--;
if (depCount == 0) {
saveModule(modName, params, factory);
}
});
})(i);
}
} else {
saveModule(modName, [], factory);
}
},
define : function(moduleName, factory, config) {
this.loadModule(moduleName, factory, config);
},
use: function(modules, factory){
this.loadModule(undefined, factory, {requires:modules});
}
};
return ISF;
})(window, document);
テスト:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<script src="ISF.js" type="text/javascript"></script>
</head>
<body>
</body>
<script type="text/javascript">
ISF.use(['util', 'math', 'num'], function (util, math, num) {
num = math.getRadom() + '_' + num;
num = util.formatNum(num);
console.log(num);
});
</script>
</html>
ISF.define('math', function (num) {
return {
getRadom: function () {
return parseInt(Math.random() * num);
}
};
}, {requires:['num']});
ISF.define('num', function () {
return 10;
});
ISF.define('util', function () {
return {
formatNum: function (n) {
if (n < 10) return '0' + n;
return n;
}
};
});