2013-08-31 45 views
5

我有一个Java背景,最近我一直在尝试JavaScript的继承。我开始写一些对象,在阅读了一些例子后,我发现了最适合我的代码风格。为什么在扩展对象时使用Object.create作为原型?

以下是我有:

var Class = function() {}; 
Class.extend = function(p_constructor) { 
    var Superclass = this; 
    // the following line confuses me 
    p_constructor.prototype = Object.create(Superclass.prototype); 
    p_constructor.prototype.constructor = p_constructor; 
    p_constructor.extend = Superclass.extend; 
    return p_constructor; 
}; 

所以现在当我想定义延伸类的对象我只需要输入:

var Person = Class.extend(function(p_firstName, p_lastName) { 
    this.firstName = p_firstName; 
    this.lastName = p_lastName; 
}); 

及以下为真:

var p = new Person('john', 'smith'); 
p instanceof Person; // true 
p instanceof Class; // true 

我只是很难理解什么是ef在Class.extend功能如下行之间fective区别:

/* 1) */ p_constructor.prototype = new Superclass(); 
/* 2) */ p_constructor.prototype = Superclass.prototype; 
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 
/* 4) */ p_constructor.prototype = Object.create(Superclass); 

我也知道使用一号线是不是很明智的,如果一些超级构造函数抛出错误,但什么也正是线2,3和4之间的区别?

回答

6

要回答我的问题:

/* 1) */ p_constructor.prototype = new Superclass(); 

就像我说的,这不是很明智的使用,因为它实际上创造了整个超类对象。原型继承的要点是共享原型对象,因此可以避免多余的函数(有时是对象)定义。

/* 2) */ p_constructor.prototype = Superclass.prototype; 

如果你能确定构造函数的原型永远不会被第三方修改,这将是确定的。假设某个使用你的类的人想要为其原型添加额外的功能。改变p_constructor的原型会直接影响超类的原型,并可能在超类的行为中引入错误。所以下一行代码来代替:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 

这将创建一个新的对象(实例),其原型(实际上是__proto__变量)设置为超类的原型。现在对p_constructor.prototype的任何更改都不会更改超类的行为。

/* 4) */ p_constructor.prototype = Object.create(Superclass); 

上面一行有效,但没有意义,因为它只将原型设置为超类的构造函数。

此外,以下行混淆了我还有:

p_constructor.prototype.constructor = p_constructor; 

这使得在p_constructor的行为没有什么区别,它不仅使参考实例化对象提供的构造函数。一个绝招就是超添加到原型,以及:

p_constructor.prototype.superclass = Superclass; 

,然后将下面的代码段将工作:

function Constructor(p_params) { 
    // call constructor of the superclass 
    this.superclass(p_params); 
} 
+0

酷,你在这里回答你的问题。在你最后一块代码中,当你这样调用超类的构造函数时,请考虑它的上下文;我认为你想要做的是'this.superclass.apply(this,arguments);' - 那么,如果super的构造函数变为'this.sumthin = ...',那么该值将附加到子类的实例。 – dalgard

+0

无论如何,来自超类的值将被附加到子类的当前实例,因为它是从'this'调用的,所以它的上下文实际上是子类的新实例。 – jeremija

+0

哦,你说得对。我想我更经常地看到这种模式:'subclass.prototype.super = superclass.prototype'(可能加上'subclass.super = superclass')。也许你有兴趣查看[我的解决方案](https://gist.github.com/dalgard/9169923)这些东西(请参阅评论中的示例)。 – dalgard

相关问题