第二版本:
1.添加了 jimport 类似实现java的import关键字
2.jclass的改进:
- 单个参数为返回查找的类,
- 第一个参数为""时,产生匿名函数。
- 从第三个参数到倒数第二个参数为mixin,且所有的mixin将按照顺序传入类定义的闭包函数的第二个参数到最后一个参数。
附上代码:
var Js5 = {version:"5.0.0"};
var __cpackage__;
var __classes__ = {};
var __iclasses__ = {};
var __imports__ = [];
Js5.apply = function(o, c) {
if (o && c && typeof c == 'object') {
for (var p in c) {
o[p] = c[p];
}
}
return o;
};
(function() {
Js5.apply(Js5, {
applyIf : function(o, c) {
if (o) {
for (var p in c) {
if (!Js5.isDefined(o[p])) {
o[p] = c[p];
}
}
}
return o;
},
extend : function() {
var oc = Object.prototype.constructor;
return function(sb, sp, overrides) {
var coverrides = overrides;
if (!overrides) {
coverrides = sp;
sp = sb;
}
var F = function() {
},sbp,spp = sp.prototype;
F.prototype = spp;
coverrides = coverrides(spp) || {};
if (!overrides) {
sb = coverrides.constructor != oc ? coverrides.constructor : function() {
sp.apply(this, arguments);
};
}
sbp = sb.prototype = new F();
sbp.constructor = sb;
sb.superclass = spp;
if (spp.constructor == oc) {
spp.constructor = sp;
}
sbp.superclass = (function() {
return spp;
});
Js5.override(sb, coverrides); // extend coverrides
return sb;
}
}(),
mixin:function() {
var oc = Object.prototype.constructor;
return function(mixins, sb, sp, overrides) {
if (!Js5.isArray(mixins)) {
mixins = [mixins];
}
var coverrides = overrides;
if (!overrides) {
coverrides = sp;
sp = sb;
}
var F = function() {
},sbp,spp = sp.prototype;
F.prototype = spp;
mixins.unshift(spp);
coverrides = coverrides.apply(this, mixins) || {};
if (!overrides) {
sb = coverrides.constructor != oc ? coverrides.constructor : function() {
sp.apply(this, arguments);
};
}
sbp = sb.prototype = new F();
sbp.constructor = sb;
sb.superclass = spp;
if (spp.constructor == oc) {
spp.constructor = sp;
}
sbp.superclass = (function() {
return spp;
});
Js5.override(sb, coverrides); // extend coverrides
mixins.shift();
Js5.each(mixins, function(mixin) {
Js5.applyIf(sbp, mixin);
});
return sb;
}
}(),
override: function(origclass, overrides) {
if (overrides) {
var p = origclass.prototype;
Js5.apply(p, overrides);
}
},
/*override : function(origclass, overrides) {
if (overrides) {
var p = origclass.prototype;
overrides = overrides(p.superclass);
Js5.apply(p, overrides);
if (Js5.isIE && overrides.hasOwnProperty('toString')) {
p.toString = overrides.toString;
}
}
},*/
isString : function(v) {
return typeof v === 'string';
},
isBoolean : function(v) {
return typeof v === 'boolean';
},
isElement : function(v) {
return !!v && v.tagName;
},
isDefined : function(v) {
return typeof v !== 'undefined';
},
isObject : function(v) {
return !!v && Object.prototype.toString.call(v) === '[object Object]';
},
isDate : function(v) {
return toString.apply(v) === '[object Date]';
},
isPrimitive : function(v) {
return Js5.isString(v) || Js5.isNumber(v) || Js5.isBoolean(v);
},
isNumber : function(v) {
return typeof v === 'number' && isFinite(v);
},
isEmpty : function(v, allowBlank) {
return v === null || v === undefined || ((Js5.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
},
isArray : function(v) {
return toString.apply(v) === '[object Array]';
},
isIterable : function(v) {
//check for array or arguments
if (Js5.isArray(v) || v.callee) {
return true;
}
//check for node list type
if (/NodeList|HTMLCollection/.test(toString.call(v))) {
return true;
}
//NodeList has an item and length property
//IXMLDOMNodeList has nextNode method, needs to be checked first.
return ((typeof v.nextNode != 'undefined' || v.item) && Js5.isNumber(v.length));
},
each : function(array, fn, scope) {
if (Js5.isEmpty(array, true)) {
return [];
}
if (!Js5.isIterable(array) || Js5.isPrimitive(array)) {
array = [array];
}
for (var i = 0, len = array.length; i < len; i++) {
if (fn.call(scope || array[i], array[i], i, array) === false) {
return i;
}
}
return [];
},
namespace : function() {
var o, d;
Js5.each(arguments, function(v) {
d = v.split(".");
o = window[d[0]] = window[d[0]] || {};
Js5.each(d.slice(1), function(v2) {
o = o[v2] = o[v2] || {};
});
});
return o;
},
nameclass:function(c) {
if (__classes__[c]) return __classes__[c];
var d = c.split(".");
var o = window[d[0]] = window[d[0]] || {};
Js5.each(d.slice(1, d.length - 1), function(v2) {
o = o[v2] = o[v2] || {};
});
return __classes__[c] = o[d[d.length - 1]];
},
importclass:function(c) {
if (__classes__[c]) return __classes__[c];
if (__iclasses__[c]) return __iclasses__[c];
var d = c.split(".");
var o = window[d[0]] = window[d[0]] || {};
var name = d[d.length - 1];
Js5.each(d.slice(1, d.length - 1), function(v2) {
o = o[v2] = o[v2] || {};
});
if (o[name]) {
o = __classes__[c] = o[name];
} else {
Js5.each(__imports__, function(i) {
if ((o = i[name])) {
return false;
}
});
__iclasses__[c] = o;
}
return o;
}
});
Js5.ns = Js5.namespace;
})();
/**
* p1:String ==>package name
* p2..p-1,Object ==>imports
* p-1,function ==> package body
*/
function jpackage() {
var l = arguments.length,i = 0;
if (l == 0) return;
var pkf = arguments[l - 1];
if (Js5.isString(arguments[0])) {
__cpackage__ = Js5.namespace(arguments[0]);
i = 1;
} else {
__cpackage__ = window;
i = 0;
}
var args = [],vs,ip;
Js5.each(Array.prototype.slice.call(arguments, i, l - 1), function(v) {
if (Js5.isString(v)) {
vs = v.split(";");
Js5.each(vs, function(v2) {
if (v2.substr(-2) == ".*") {
ip = Js5.namespace(v2.substring(0, v2.length - 2));
__imports__.push(ip);
args.push(ip);
} else {
args.push(Js5.importclass(v2));
}
});
} else if (Js5.isArray(v)) {
args = args.concat(v);
} else {
args.push(v);
}
});
pkf.apply(__cpackage__, args);
__cpackage__ = null;
__imports__ = [];
__iclasses__ = {};
}
function jimport() {
var args = [],vs,ip;
__imports__ = [];
__iclasses__ = {};
Js5.each(arguments, function(v) {
if (Js5.isString(v)) {
vs = v.split(";");
Js5.each(vs, function(v2) {
if (v2.substr(-2) == ".*") {
ip = Js5.namespace(v2.substring(0, v2.length - 2));
__imports__.push(ip);
args.push(ip);
} else {
args.push(Js5.importclass(v2));
}
});
} else if (Js5.isArray(v)) {
args = args.concat(v);
} else {
args.push(v);
}
});
return args;
}
/**
* p1:String ==>class name
* p2,String ==>same package;Object
* p3,function ==>
*/
function jclass() {
var l = arguments.length,i = 0;
if (l == 0) {
throw new Error("[jclass] invalid arguments");
}
if (l == 1) {
return Js5.importclass(arguments[0]);
}
var clf = arguments[l - 1];
var c;
if (Js5.isString(arguments[0])) {
c = __cpackage__;
} else {
c = window;
}
var p;
if (l >= 3) {
var name = arguments[1];
if (Js5.isString(name)) {
p = __cpackage__[name];
if (!p) {
p = Js5.importclass(name);
}
} else {
p = arguments[1];
}
} else {
p = Object;
}
if (!p) {
throw new Error("[jclass] unrecognized parent class");
}
var mixins = [];
if (l >= 4) {
var vs;
var mc;
Js5.each(Array.prototype.slice.call(arguments, 2, l - 1), function(v) {
if (Js5.isString(v)) {
vs = v.split(",");
Js5.each(vs, function(v2) {
mc = Js5.importclass(v2);
if (mc) {
mixins.push(mc.prototype);
}
});
} else {
mixins.push(v.prototype);
}
});
}
var cls = Js5.mixin(mixins, p, clf);
if (arguments[0]) {
c[arguments[0]] = cls;
}
return cls;
}
function jnew() {
var l = arguments.length,i = 0;
if (l == 0) return {};
var args = Array.prototype.slice.call(arguments, 1);
var name = arguments[0];
var cls;
if (Js5.isString(name)) {
if (__cpackage__ && __cpackage__[name]) {
cls = __cpackage__[name];
}
if (!cls) {
cls = Js5.importclass(name);
}
if (!cls) {
throw new Error("[jnew] unrecognized class");
}
} else {
cls = name;
}
/*var temp = function() {
};
var constructor = cls.prototype.constructor;
var instanceCls = function() {
return constructor.apply(this, args);
};
temp.prototype = cls.prototype;
instanceCls.prototype = new temp();
instanceCls.prototype.constructor = instanceCls;
return new instanceCls();*/
var obj = {};
Js5.override(obj, cls);
obj.__proto__ = cls.prototype;
cls.apply(obj, args);
return obj;
}
例子:
var jui = {};
jpackage("jui", function() {
jclass("Component", function() {
return {
constructor:function(x) {
console.log("Component:" + x);
},
show:function() {
console.log("Component");
}
}
});
jclass("Container", "Component", function(_supr) {
return {
constructor:function(x) {
console.log("Container:" + x);
_supr.constructor.call(this, x);
}
};
});
});
jpackage("jui", function() {
jclass("Window", "Container", function(_supr) {
return {
show:function() {
console.log("Window");
}
}
});
});
jpackage("jui.form", function() {
jimport("jui.*");
jclass("TextField", "Component", function(_supr) {
return {
show:function() {
console.log("TextField");
}
}
});
});
jpackage("js5.util", function() {
jclass("Observable", function(_supr) {
return {
constructor:function() {
console.log("Observable.constructor");
},
on:function() {
console.log("Observable.on");
},
show:function() {
console.log("Observable.show");
}
}
});
});
jpackage("jui.ex", jimport("jui.Window;jui.*;jui.form.*"), function(_W, j) {
jclass("Window", "jui.Window", "js5.util.Observable", function(_supr, _ob) {
return {
constructor:function(x) {
console.log("jui.ex.Window.constructor");
_supr.constructor.call(this, x);
_ob.constructor.call(this);
},
show:function() {
console.log("Window Ex");
_supr.show();
}
}
});
var MyWindow = jclass("", "jui.Window", function() {
return {
show:function() {
console.log("anonymous myWindow");
}
}
});
var x = jnew("Window", "package jui.ex.Window");
x.show();
x.on();
x = new MyWindow();
x.show();
jclass("jui.Window").superclass.constructor.call(this, "111111111111")
x = jnew(jui.Window, "jui.Window : new in package, use complete class path");
x.show();
x = new jui.Window("jui.Window : new in package, use complete class path");
x.show();
x = jnew("jui.Window", "jui.Window: new in package, use complete class path");
x.show();
x = new j["Window"]("jui.Window: new in package, use import jui.*");
x.show();
x = new _W("jui.Window: new in package, use import jui.Window");
x.show();
for (var i = 1; i <= 5; i++) {
x = jnew("TextField", "jui.form.TextField new in package,use import jui.form.*");
x.show();
}
});
var x = jnew("jui.ex.Window", "global jui.ex.Window");
x.show();
本文介绍了一种自定义脚本方法,用于在JavaScript中创建复杂的类结构,包括导入、命名空间、类继承和混合应用。通过示例展示了如何在不同包内创建组件、容器、窗口等类,并在不同包间进行类引用和导入,实现模块化编程。
4万+

被折叠的 条评论
为什么被折叠?



