javascript继承学习(一)

网上的众多javascript继承方式,这里是不会详细讲解的,需要的,请自己度娘或谷爹。


之前做cocos2d-js的游戏,发现它有一个很有趣的继承方式。

形式如下:

var A = cc.Class.extend({
	// 一系列的函数等
        ctor: function(){
               // this._super指向了父亲的ctor方法,不明觉厉啊
               this._super();
        }
});

于是研究了一下,主要有几点需要注意的:

1、function.toString会返回整个函数的定义字符串
2、str.indexOf方法,有两个参数,第一个是字符串,第二个是起始检查的位置,它第一次匹配上,就结束了
3、它的this._super方法,是通过匹配 闭包改写,弄出来的


于是,尝试了一下,自己去实现:

function Class(){};

// compileSuper在某些特定情况下,才有用咯~,不过,它更节省内存空间,如果不需要调试,可以启用这种继承
Class.compileSuper = function(fnStr, fnName){
	// 找出fn的参数
	var pstart = fnStr.indexOf("("), pend = fnStr.indexOf(")");
	var params = fnStr.slice(pstart + 1, pend);
	
	// 从fn主体开始寻找
	var str = fnStr.substring(fnStr.indexOf("{") + 1, fnStr.lastIndexOf("}"));
	
	// 替换掉this._super,为this.super[name]
	// cocos2d-js里,是通过for循环来实现的,但因为这里多记录了一个super字段,所以没有它的烦恼~
	var keyName = "this.super." + fnName;
	str = str.replace(/this._super/g, "this.super && " + keyName + " && " + keyName);
	
	// 返回新的函数
	return new Function(params, str);
};

Class.extend = function(proto){
	var _super = this.prototype;
	function myClass(){
		this.ctor && this.ctor.apply(this, arguments);
	};
	var fn = myClass.prototype;
	// 下面这个for循环,如果再包装一下,就可以实现多参数形式了~,实验,不过多考虑
	for(var key in proto){
		// 当前的item
		var item = proto[key];
		// 如果父类和当前,都是函数,则有继承关系
		var isSuperFunc = "function" == typeof _super[key], isFunc = "function" == typeof item;
		if(isFunc && isSuperFunc){
			// 实现继承,包装一个super方法,如果存在_super这样的字段,则编译
			var reg = /\b_super\b/, itemStr = item.toString();
			if(reg.test(itemStr)){
				// 有_super方法,则编译super方法
				// 但是一点都不好调试,可以考虑在其它模式下【如不想被别人调试的时候...】,使用这种编译
				// 这里主要做实验,就不一一操作了
				// fn[key] = Class.compileSuper(itemStr, key);

				// 放弃编译的方法,使用闭包
				fn[key] = (function(key, proto){
					return function(){
						var tmp = this._super;
						// 这一句依赖后面的 fn.super = _super;
						this._super = this.super[key];
						var res = item.apply(this, arguments);
						this._super = tmp;
						return res;
					};
				})(key, item);		
				
			}else{
				fn[key] = item;
			}
		}else{
			fn[key] = item;
		}
	};
	// 可以通过super寻找到父类
	fn.super = _super;
	myClass.extend = fn.extend = Class.extend;
	return myClass;
};


因无法调试等原因,丢弃了匹配【重新编译字符串】的实现,使用了闭包。

但是闭包带来了额外的内存消耗,所以,如果真正上线,最好还是使用匹配的实现。


下面看两个例子:

var myFirst = Class.extend({
	constroctor: myFirst,
	ctor: function(name){
		// 因为父类Class,没有ctor方法,所以this._super(name);的调用,会报错
		// this._super(name);
		console.log(name);
	}
});

var mySecond = myFirst.extend({
	ctor: function(name, age){
		// 继承了myFirst,因为myFirst有ctor方法,所以,this._super(name)正常使用
		this._super(name);
		console.log(age);
	}
});

// 最终数据:
var ss = new mySecond("da宗熊", 26);
// 输出: da宗熊 26


代码看着挺优雅的,

但这种实现,也有一定的局限性:

1、约定了ctor为构造函数,new操作,实际调用了ctor的操作【可容忍】

2、继承没有筛选属性,会把父类的所有属性继承下来

3、链太深之后,会造成子类过度臃肿


个人觉得,较为简单的项目,是完全没必要使用的。

只有项目中,有强烈的上下级继承关系的时候,才是它发光发热的时候。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值