JavaScript原型和调用()

时间:2014-04-20 19:07:00

标签: javascript prototypejs

我正在学习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(); 

4 个答案:

答案 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);