我正在学习js原型,我想知道以下两段之间是否有任何差异?
SEGMENT1:
function SuperType(){
this.color=["blue","yellow"];
}
function SubType(){
}
Subtype.prototype = new SuperType();
分段2 :
function SuperType(){
this.color=["blue","yellow"];
}
function SubType(){
SuperType.call(this);
}
如果以上两个做同样的事情,那么为什么有些代码会这么做呢:
function SubType(){
SuperType.call(this);
}
SubType.prototype=new SuperType();
答案 0 :(得分:2)
是的,存在差异。
在段1中,子类SubType
不会调用SuperType
的构造函数,因此它永远不会被执行。段1不是从另一个对象继承的正确通用方法。
在段2中,子类SubType
确实调用了SuperType
的构造函数,因此语句this.color=["blue","yellow"];
被执行,但原型未正确设置,因此任何原型项{{1}可能已经没有继承过。段2不是从另一个对象继承的正确通用方法。
如果SuperType
构造函数中没有代码(在您的示例中不是这种情况),则段1将正常工作。当你展示它时,因为没有调用SuperType
构造函数,SuperType()
只会在原型中,因此所有实例都会共享同一个数组,这通常不是你想要的。正确调用构造函数会为每个实例提供它自己的this.color
副本,而不是共享副本。
如果this.color
原型没有添加任何内容且SuperType
没有构造函数参数,则段2将正常工作(在您的示例中恰好是这种情况,但不是一般的惯例)。
两者都不是一种很好的通用方式。
你的最后一个选项是正确的通用方法,因为它都继承自原型并且它执行继承对象的构造函数。
最通用的方法还使用SuperType
这样的任何构造函数参数传递给继承的对象,并初始化它自己的原型并设置它的构造函数属性。
.apply(this, arguments)
如果您愿意仅支持IE9及更高版本,那么您应该更改此行:
// define base object constructor
function SuperType(){
this.color=["blue","yellow"];
}
// define base object methods on the prototype
SuperType.prototype.foo = function() {};
// ---------------------------------------------------------------------------
// define object that wants to inherit from the SuperType object
function SubType() {
// call base object constructor with all arguments that might have been passed
SuperType.apply(this, arguments);
}
// set prototype for this object to point to base object
// so we inherit any items set on the base object's prototype
SubType.prototype = new SuperType();
// reset constructor to point to this object not to SuperType
SubType.prototype.constructor = SubType;
// define any methods of this object by adding them to the prototype
SubType.prototype.myMethod = function() {};
到此:
SubType.prototype = new SuperType();
这可以避免调用SubType.prototype = Object.create(SuperType.prototype);
构造函数,以便只获取用于原型的对象。在大多数情况下,这并不重要,但是如果构造函数在初始化它自己的属性之外有副作用,那就很重要。
答案 1 :(得分:1)
在第1段中,原型设置正确,但SuperType
的构造函数永远不会被调用。
在段2的开头,调用SuperType
的构造函数,但未设置原型。
最后一个例子是正确的,因为它正确设置原型并调用SuperType
的构造函数。
function SuperType() {
// Do some stuff.
}
function SubType() {
SuperType.apply(this, arguments);
}
SubType.prototype = new SuperType();
答案 2 :(得分:1)
你不应该用
设置原型继承 SubType.prototype=new SuperType ();
因为可能存在问题。
如果你这样做,SubType的原型也会继承属性颜色作为SubType原型的自己的属性,因为构造函数是通过的。每个新的subType实例都有一个对原型中color属性的引用,并且不是实例本身的属性,这最终不是你想要的,因为你只想继承原型。幸运的是,在调用超级构造函数之后,每个实例都获得了自己的颜色属性,但颜色属性仍然在原型中定义。没有必要
所以要真正继承原型,你应该使用Object.create或做一个像这样的解决方法。
function SuperType()
{
if (SuperType.doNotConstruct) return;
this.color=["blue","yellow"];
}
function SubType()
{
SuperType.call (this);
}
SuperType.doNotConstruct=true;
SubType.prototype = new SuperType();
SuperType.doNotConstruct=false;
SubType.prototype.constructor=SubType;
第二种方式 - 更好的方法 - 因为在构造函数中不需要语句
function SuperType()
{
this.color=["blue","yellow"];
}
function SubType()
{
SuperType.call (this);
}
var CLASS=function () {}
CLASS.prototype=SuperType.prototype;
SubType.prototype=new CLASS ();
SubType.prototype.constructor=SubType;
答案 3 :(得分:0)
@blake尝试以下操作 - 当人们忘记调用超级构造函数并使用... prototype = new constructor
进行继承时,这将显示一个问题function SuperType()
{
this.color=["blue","yellow"];
}
SuperType.prototype.addColor=function (name)
{
this.color.push ("red");
}
function SubType () {}
SubType.prototype=new SuperType ();
var a=new SubType ();
var b=new SubType ();
a.addColor ("red");
console.log (a.color);
console.log (b.color);