1, 缺点,给子类prototype添加新方法只能一个一个添加,不能直接传一个对象(方法集合),否则会覆盖继承的父类的方法。
1 Function.prototype.inherit = function(baseClass){ 2 for(var i in baseClass.prototype){ 3 this.prototype[i] = baseClass.prototype[i]; 4 } 5 } 6 function BaseClass(){} 7 BaseClass.prototype = { 8 method1:function(){ 9 alert('method1'); 10 }, 11 method2:function(){ 12 alert('method2'); 13 } 14 }; 15 16 function ClassA(){} 17 ClassA.inherit(BaseClass); 18 ClassA.prototype.method1 = function(){alert(0);}; 19 var obj = new ClassA(); 20 obj.method1(); 21 var obj2 = new BaseClass(); 22 obj2.method1();
2, 缺点是继承必须Class.prototype = (new BaseClass()).extend({.....});这样写,习惯了java这类面向对象语言的继承的人,估计看着这样的写法会有点别扭,比如我就觉得这样挺别扭的。不过习惯了就好,jquery的继承写法不也跟这样类似么。其实下面这代码就是prototype-1.3.1框架里继承的写法。我按照书上写的。
Object.extend = function(des,source){ for(var property in source){ des[property] = source[property]; } return des; }; Object.prototype.extend = function(object){ return Object.extend.apply(this,[this,object]); }; function BaseClass(){ this.name = "name"; }; BaseClass.prototype = { method1:function(){alert('method1');}, method2:function(){alert('method2');} }; function Class(){}; Class.prototype = (new BaseClass()).extend({ method1:function(){alert('extend');}, m1:function(){alert('m1');},
age:'age' }); var a = new Class(); a.method1(); a.method2(); a.m1(); alert(a.name);
留给自己的问题,如果有谁看到, 并且知道,请告知,谢谢。
这种写法,会将父类构造器里定义的属性也赋给继承类的prototype,即使这些属性的值是undefined,占不占用内存?如果继承时候用apply或者call来继承了基类的属性,如
1 function BaseClass(name){ 2 this.name = name; 3 }; 4 function Class(name,age){ 5 BaseClass.call(this, name); 6 };
然后再用上面的 Class.prototype = (new BaseClass()).extend({.....}); 这个时候,Class有一个name属性,而Class.prototype里应该是也有个name属性,只不过它的值是undefined。在使用的时候,似乎是没有什么问题的,可是我突然想,Class.prototype.name是否会占用一个空间呢?如果占用,这个空间被占用却又没有什么用处,然而这点被占用的空间几乎又并不是很大,是忽略它呢还是应该去优化呢?哎,想到这里,似乎这又并不是一个什么问题了,一个类浪费了这么一点空间,似乎并不是什么大问题。
2014.4.16 补充编辑
接上面的问题,Class.prototype.name是一个属性,自然会占用空间,只不过它指向了window.undefined。这在对Class的对象的属性查找时候,会增加资源消耗。
解决办法:自定义一个prototype对象,将构造函数也定义在prototype对象里,然后用一个通用函数来创建类的实例对象。
如下
1 //通用创建函数 2 function New(aClass, aParams) 3 { 4 function new_() 5 { 6 //调用原型中定义的构造函数,中转构造逻辑及构造参数 7 aClass.Create.apply(this,aParams); 8 }; 9 //中转原型对象 10 new_.prototype = aClass; 11 //返回最终建立的对象,在退出函数体的时候,new_ 函数对象会被释放。 12 return new new_(); 13 }; 14 //定义的类(自定义的原型,将类的构造函数放在原型对象里) 15 var Person = { 16 Create:function(name,age) 17 { 18 this.name = name; 19 this.age = age; 20 }, 21 SayHello:function() 22 { 23 alert("Hello,I'm " + this.name); 24 }, 25 HowOld:function() 26 { 27 alert(this.name + " is " + this.age + " years old."); 28 } 29 }; 30 31 //调用通用函数创建对象,并以数组形式传递构造参数 32 var BillGates = New(Person,["Bill Gates",59]); 33 BillGates.SayHello(); 34 BillGates.HowOld();
这种写法,很类似于c#的对象语言形式,代码看起来会很优雅。而且这种写法的JavaScript 程序效率会更高。因为其原型对象里既没有了毫无用处的那些对象级的成员,而且还不存在constructor 属性体(新建的对象自己及其原型里没有constructor 属性,返回的是最顶层原型对象的构造函数,即Object),少了与构造函数间的牵连,但依旧保持了方法的共享性。这让JavaScript 在追溯原型链和搜索属性及方法时,会快捷一些。
用于继承也是一样的,如
1 //通用的继承方法(自定义的prototype对象) 2 function Class(aBaseClass, aClassDefine){ 3 function class_(){ 4 //Type指向基类 5 this.Type = aBaseClass; 6 for(var member in aClassDefine){ 7 //复制类的全部定义到当前创建的类 8 this[member] = aClassDefine[member]; 9 } 10 }; 11 class_.prototype = aBaseClass; 12 return new class_(); 13 } 14