将继承隔离成函数

时间:2011-08-16 17:21:38

标签: javascript

http://jsbin.com/ifoguf/14/edit#javascript

我尝试将继承部分隔离到一个函数中,但是当我创建该对象时,nothings会被警告,不会返回任何错误,所以我很难理解如何调试,以及解决方案。

function Shape(){}
// augment prototype
Shape.prototype.name = 'shape';
Shape.prototype.toString = function() {return this.name;};

function TwoDShape(){}


// augment prototype
TwoDShape.prototype.name = '2D shape';



function Triangle(side, height) {
this.side = side;
this.height = height;
}


// augment prototype
Triangle.prototype.name = 'Triangle';
Triangle.prototype.getArea = function(){return this.side * this.height / 2;};




var myTriangle = new Triangle(5, 10);

function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}


extend(TwoDShape, Shape);
extend(Triangle, TwoDShape);


var myTriangle = new Triangle(5, 10);


alert(myTriangle.getArea());

alert(myTriangle.toString());

var s = new Shape();
alert(s.name);

TIA

1 个答案:

答案 0 :(得分:1)

您的代码似乎有点复杂。查看更简单的example(记得打开调试工具以查看日志消息)。

值得注意的是,JavaScript中的继承通过遵循原型链来实现。这意味着每个对象都拥有对原型对象的引用。这个原型对象也是任何普通对象。关键是无论何时在对象中找不到属性(或函数),都会检查其原型对象。这遵循原型链接,直到找到值或没有原型遗留下来。

每当创建对象时,原型链接都存储在对象中,并指向对象的构造函数的prototype属性中指定的对象。您可以通过检查对象的__proto__ property来检查Firefox中的原型。

在链接的示例中,有3个构造函数:

  • 形状
  • 三角
  • createPrototype(帮助获取具有已定义原型链接的空对象)

在链接示例中,有2个原型对象:

  • Shape.prototype(包含形状的共享属性)
  • Triangle.prototype(包含三角形的共享属性)

首先通过调用new Shape()创建一个形状。这会创建一个新对象,因为new写在名为Shape的函数前面。对象的原型链接(Firefox中的__proto__)指向Shape.prototype,因为构造函数的此属性提供了原型链接的目标。链接在对象实例化时设置。

因此,每当您尝试访问shape的属性时,将按如下方式检索该属性。首先,搜索shape属性。如果它在那里,使用它。如果不是,则检索原型对象shape.__proto__,该对象引用与Shape.prototype相同的对象。现在,搜索原型对象的属性。

对于三角形的情况,事情有点复杂,因为涉及多个原型链接。重要的是我们需要创建一个空对象来保存三角形的共享属性,这些属性也需要将其原型链接设置为指向Shape.prototype。这使得形状的原型成为三角形原型的后备 它由包含createPrototype的匿名函数存档。需要包含它,因为匿名函数的每次调用都需要操作构造函数的prototype属性(在我们的例子中称为createPrototype)。在创建具有原型链的空原型对象之后,立即返回并分配给Triangle.prototype。之后,new Triangle()创建的任何对象都具有所需的原型链。

设置完成后,我们可以将三角形的所有共享属性添加到刚刚创建的Triangle.prototype对象中。通过覆盖paint和添加getArea来显示此信息。请注意,此覆盖实际上有效,因为三角形的paint函数早于形状的paint方法,并且使用了第一个找到的引用/属性。

总而言之,对象上的所有属性访问都使用原型链进行回退。在我们的例子中,shape的链是shapeShape.prototype,而triangle的链是[{1}}→triangleTriangle.prototype

您可能希望为匿名函数(包括Shape.prototype)指定一个名称,以便为创建的对象层次结构提供工具。这显示在updated example中,最后是以下帮助程序:

createPrototype