这段代码是正在使用的一个小框架,发现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