kityminder
Version:
209 lines (173 loc) • 7.21 kB
JavaScript
/**
* @description 创建一个类
* @param {String} fullClassName 类全名,包括命名空间。
* @param {Plain} defines 要创建的类的特性
* defines.constructor {Function} 类的构造函数,实例化的时候会被调用。
* defines.base {String} 基类的名称。名称要使用全名。(因为base是javascript未来保留字,所以不用base)
* defines.mixin {Array<String>} 要混合到新类的类集合
* defines.<method> {Function} 其他类方法
*
* TODO:
* Mixin 构造函数调用支持
*/
define(function(require, exports) {
// just to bind context
Function.prototype.bind = Function.prototype.bind || function(thisObj) {
var args = Array.prototype.slice.call(arguments, 1);
return this.apply(thisObj, args);
};
// 所有类的基类
function Class() {}
Class.__KityClassName = 'Class';
// 提供 base 调用支持
Class.prototype.base = function(name) {
var caller = arguments.callee.caller;
var method = caller.__KityMethodClass.__KityBaseClass.prototype[name];
return method.apply(this, Array.prototype.slice.call(arguments, 1));
};
// 直接调用 base 类的同名方法
Class.prototype.callBase = function() {
var caller = arguments.callee.caller;
var method = caller.__KityMethodClass.__KityBaseClass.prototype[caller.__KityMethodName];
return method.apply(this, arguments);
};
Class.prototype.mixin = function(name) {
var caller = arguments.callee.caller;
var mixins = caller.__KityMethodClass.__KityMixins;
if (!mixins) {
return this;
}
var method = mixins[name];
return method.apply(this, Array.prototype.slice.call(arguments, 1));
};
Class.prototype.callMixin = function() {
var caller = arguments.callee.caller;
var methodName = caller.__KityMethodName;
var mixins = caller.__KityMethodClass.__KityMixins;
if (!mixins) {
return this;
}
var method = mixins[methodName];
if (methodName == 'constructor') {
for (var i = 0, l = method.length; i < l; i++) {
method[i].call(this);
}
return this;
} else {
return method.apply(this, arguments);
}
};
Class.prototype.pipe = function(fn) {
if (typeof(fn) == 'function') {
fn.call(this, this);
}
return this;
};
Class.prototype.getType = function() {
return this.__KityClassName;
};
Class.prototype.getClass = function() {
return this.constructor;
};
// 检查基类是否调用了父类的构造函数
// 该检查是弱检查,假如调用的代码被注释了,同样能检查成功(这个特性可用于知道建议调用,但是出于某些原因不想调用的情况)
function checkBaseConstructorCall(targetClass, classname) {
var code = targetClass.toString();
if (!/this\.callBase/.test(code)) {
throw new Error(classname + ' : 类构造函数没有调用父类的构造函数!为了安全,请调用父类的构造函数');
}
}
var KITY_INHERIT_FLAG = '__KITY_INHERIT_FLAG_' + (+new Date());
function inherit(constructor, BaseClass, classname) {
var KityClass = eval('(function ' + classname + '( __inherit__flag ) {' +
'if( __inherit__flag != KITY_INHERIT_FLAG ) {' +
'KityClass.__KityConstructor.apply(this, arguments);' +
'}' +
'this.__KityClassName = KityClass.__KityClassName;' +
'})||0');
KityClass.__KityConstructor = constructor;
KityClass.prototype = new BaseClass(KITY_INHERIT_FLAG);
for (var methodName in BaseClass.prototype) {
if (BaseClass.prototype.hasOwnProperty(methodName) && methodName.indexOf('__Kity') !== 0) {
KityClass.prototype[methodName] = BaseClass.prototype[methodName];
}
}
KityClass.prototype.constructor = KityClass;
return KityClass;
}
function mixin(NewClass, mixins) {
if (false === mixins instanceof Array) {
return NewClass;
}
var i, length = mixins.length,
proto, method;
NewClass.__KityMixins = {
constructor: []
};
for (i = 0; i < length; i++) {
proto = mixins[i].prototype;
for (method in proto) {
if (false === proto.hasOwnProperty(method) || method.indexOf('__Kity') === 0) {
continue;
}
if (method === 'constructor') {
// constructor 特殊处理
NewClass.__KityMixins.constructor.push(proto[method]);
} else {
NewClass.prototype[method] = NewClass.__KityMixins[method] = proto[method];
}
}
}
return NewClass;
}
function extend(BaseClass, extension) {
if (extension.__KityClassName) {
extension = extension.prototype;
}
for (var methodName in extension) {
if (extension.hasOwnProperty(methodName) &&
methodName.indexOf('__Kity') &&
methodName != 'constructor') {
var method = BaseClass.prototype[methodName] = extension[methodName];
method.__KityMethodClass = BaseClass;
method.__KityMethodName = methodName;
}
}
return BaseClass;
}
Class.prototype._accessProperty = function() {
return this._propertyRawData || (this._propertyRawData = {});
};
exports.createClass = function(classname, defines) {
var constructor, NewClass, BaseClass;
if (arguments.length === 1) {
defines = arguments[0];
classname = 'AnonymousClass';
}
BaseClass = defines.base || Class;
if (defines.hasOwnProperty('constructor')) {
constructor = defines.constructor;
if (BaseClass != Class) {
checkBaseConstructorCall(constructor, classname);
}
} else {
constructor = function() {
this.callBase.apply(this, arguments);
this.callMixin.apply(this, arguments);
};
}
NewClass = inherit(constructor, BaseClass, classname);
NewClass = mixin(NewClass, defines.mixins);
NewClass.__KityClassName = constructor.__KityClassName = classname;
NewClass.__KityBaseClass = constructor.__KityBaseClass = BaseClass;
NewClass.__KityMethodName = constructor.__KityMethodName = 'constructor';
NewClass.__KityMethodClass = constructor.__KityMethodClass = NewClass;
// 下面这些不需要拷贝到原型链上
delete defines.mixins;
delete defines.constructor;
delete defines.base;
NewClass = extend(NewClass, defines);
return NewClass;
};
exports.extendClass = extend;
});