仅仅继承Prototype
添加可以重用的方法和属性到prototype是非常有效率的。如果都这么做的话,为什么不仅仅继承prototype呢。也就是说我们继承prototype比继承new出来的对象要好的多。毕竟这个new的对象包含的代码并不是我们想复用的。
这样继承的优点如下,不用仅仅为了继承而创建一个对象。缩短了查找方法的时间。
更新后的集成代码如下:
function Shape(){} Shape.prototype.name = 'shape'; Shape.prototype.toString = function() {return this.name;}; function TwoDShape(){} TwoDShape.prototype = Shape.prototype;//重点 TwoDShape.prototype.constructor = TwoDShape; TwoDShape.prototype.name = '2D shape'; function Triangle(side, height) { this.side = side; this.height = height; } Triangle.prototype = TwoDShape.prototype;//重点 Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){return this.side * this.height / 2;}
测试一下
var my = new Triangle(5, 10); my.getArea();//25 my.toString();//Triangle
当查询toString的方法和以前的例子有什么不同么?首先,查询my对象自身的属性,发现没有,再检查prototype,要记住对象的copy并不是值的copy,而是引用。所以它们共同的prototype指向一个地址。也就是说 仅仅检查两个步骤就完成了上面复杂的检查。虽然这个方法很有效率,但是因为指向的是同一地址所以要注意以下的情况。
Triangle.prototype.name = 'Triangle'; var s = new Shape() s.name;//Triangle
临时的构造函数 new F()
上面的例子的问题还是很严重的,父对象取到子对象的属性了,必须要解决的。可以想一个中间层打破这个链。
方法就是用个临时的构造函数。
function Shape(){} Shape.prototype.name = 'shape'; Shape.prototype.toString = function() {return this.name;}; function TwoDShape(){} var F = function(){}; F.prototype = Shape.prototype; TwoDShape.prototype = new F();//注意这里 TwoDShape.prototype.constructor = TwoDShape; TwoDShape.prototype.name = '2D shape'; function Triangle(side, height) { this.side = side; this.height = height; } var F = function(){}; F.prototype = TwoDShape.prototype; Triangle.prototype = new F();//注意这里 Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){return this.side * this.height / 2;};
var my = new Triangle(5,10);
my.getArea();//25
my.toString();//Triangle
var s = new Shape();
s.name;//Shape
这样就避免了上面说的问题。