发布日期:2015-11-25 21:36:42

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

发表评论