这段代码是正在使用的一个小框架,发现extend的实现有点问题,于是深入研究下js的继承实现的细节问题。
Class=function(){
var klass = function(){
this.init.apply(this,arguments);
}
klass.prototype.init = function(){};
klass.supper = function(){};
klass.extend = function(supperClass){
for(var prop in supperClass){
klass.prototype[prop] = supperClass[prop];
}
klass.supper = supperClass;
};
klass.proxy = function(func){
var self = this;
return (function(){return func.apply(self,arguments);});
};
klass.prototype.proxy = klass.proxy;
return klass;
}
如果我有一个classA:
MyClassA = new Class();
MyClassA.extend({
sayhello: function(){
console.log("hello classA");
}
});
创建一个classB,如果只是简单的继承classB的话,就有问题。
MyClassB = new Class(); MyClassB.extend(MyClassA); var b = new MyClassB(); b.sayhello();//会有问题,因为MyClassA是个function TypeError: Object [object Object] has no method 'sayhello'
那如何解决这个问题?
MyClassB = new Class();
MyClassB.extend(new MyClassA());
var b = new MyClassB();
b.sayhello();// "hello ClassA"
这样写是可以了,但是看起来怪怪的,为什么我的MyClassB继承的时候要写成extend myClassA(),不符合我们java程序员的习惯。怎么办?
var obj = new Base();
等价于
var obj={};
obj.__proto__=Base.prototype;
Base.call(obj);
学习下jQuery的extend实现:
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
//如果第一个值为bool值,那么就将第二个参数作为目标参数,同时目标参数从2开始计数
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// 当目标参数不是object 或者不是函数的时候,设置成object类型的
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
//如果extend只有一个函数的时候,那么将跳出后面的操作
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// 仅处理不是 null/undefined values
if ( (options = arguments[ i ]) != null ) {
// 扩展options对象
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// 如果目标对象和要拷贝的对象是恒相等的话,那就执行下一个循环。
if ( target === copy ) {
continue;
}
// 如果我们拷贝的对象是一个对象或者数组的话
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
//不删除目标对象,将目标对象和原对象重新拷贝一份出来。
target[ name ] = jQuery.extend( deep, clone, copy );
// 如果options[name]的不为空,那么将拷贝到目标对象上去。
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// 返回修改的目标对象
return target;
};
YUI的extend实现
extend: function(subc, superc, overrides) {
if (!superc||!subc) {
throw new Error("YAHOO.lang.extend failed, please check that " +
"all dependencies are included.");
}
var F = function() {};
F.prototype=superc.prototype;
subc.prototype=new F();
subc.prototype.constructor=subc;
subc.superclass=superc.prototype;
if (superc.prototype.constructor == Object.prototype.constructor) {
superc.prototype.constructor=superc;
}
if (overrides) {
for (var i in overrides) {
subc.prototype[i]=overrides[i];
}
YAHOO.lang._IEEnumFix(subc.prototype, overrides);
}
}
未完。。。
待参考文档:
http://www.cnblogs.com/yupeng/archive/2012/03/11/2389997.html
http://www.cnblogs.com/gaojun/p/4153781.html
http://www.blogjava.net/jasmine214--love/archive/2010/06/20/324018.html
http://blog.csdn.net/xuemoyao/article/details/19021659
http://www.cnblogs.com/andyliu007/archive/2012/07/27/2795415.html