繁体   English   中英

JavaScript原型和call()

[英]JavaScript prototype and call()

我正在学习js原型,并且想知道以下两个部分之间是否有任何区别?

细分1:

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(); 

是的,有差异。

在段1中,子类SubType不会调用SuperType的构造函数,因此它永远不会执行。 段1不是从另一个对象继承的正确通用方法。

在段2中,子类SubType确实调用了SuperType的构造函数,因此语句this.color=["blue","yellow"]; 被执行,但是原型设置不当,因此不会继承SuperType可能拥有的任何原型项。 段2不是从另一个对象继承的正确通用方法。

如果SuperType构造函数中没有代码,则段1将正常工作(在您的示例中不是这种情况)。 如您所示,由于未调用SuperType()构造函数,因此this.color仅在原型中,因此所有实例将共享同一数组,这通常不是您想要的。 正确调用构造函数将为每个实例提供this.color的自己副本,而不是共享副本。

如果没有向SuperType原型添加任何内容并且没有SuperType构造函数参数,则第2部分将正常工作(在您的示例中可能是这种情况,但不是很好的常规做法)。

通用的工作方式也不是。


最后一个选择是正确的通用处理方式,因为它既从原型继承,又执行继承对象的构造函数。


最通用的方法还使用.apply(this, arguments)这样将任何构造函数参数传递给继承的对象.apply(this, arguments)并初始化其自己的原型并设置其构造函数属性。

// 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() {};

如果您只支持IE9及更高版本,则应更改以下行:

SubType.prototype = new SuperType();

对此:

SubType.prototype = Object.create(SuperType.prototype);

这避免了为了获得用于原型的对象而调用SuperType()构造函数。 在大多数情况下,这确实无关紧要,但是在构造函数具有仅初始化其自身属性之外的副作用的情况下,这很重要。

在第1部分中,原型已正确设置,但从未调用SuperType的构造函数。

在第2段的开头,将调用SuperType的构造函数,但未设置原型。

最后一个示例是正确的,因为它可以正确设置原型并调用SuperType的构造函数。

function SuperType() {
  // Do some stuff.
}

function SubType() {
  SuperType.apply(this, arguments);
}

SubType.prototype = new SuperType();

你不应该设置原型继承

 SubType.prototype=new SuperType (); 

因为可能会有问题。

如果您这样做,SubType的原型也将继承属性color作为SubType原型的自己的属性,因为构造器已完成工作。 然后,每个subType的新实例都具有对原型中color属性的引用,而不是实例本身的自身属性,这最终不是您想要的,因为您只想继承原型。 幸运的是,在调用超级构造函数之后,每个实例都获得了自己的color属性,但是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;

第二种方法-更好的方法-因为不需要if构造函数中的Statement

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;

@blake尝试以下操作-当人们忘记调用超级构造函数并使用... prototype = new构造函数进行继承时,这将显示一个问题

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM