简体   繁体   English

JavaScript原型和call()

[英]JavaScript prototype and call()

I am learning the js prototype, and I am wondering if there are any differences between the following two segment? 我正在学习js原型,并且想知道以下两个部分之间是否有任何区别?

Segment1: 细分1:

function SuperType(){
    this.color=["blue","yellow"];
}


function SubType(){

}      
Subtype.prototype = new SuperType();

Segment2 : 细分2

function SuperType(){
    this.color=["blue","yellow"];
}

function SubType(){
    SuperType.call(this);
}   

and if the above two does the same thing, then why some codes bother to do this: 并且如果以上两个功能做的相同,那么为什么有些代码会麻烦这样做:

function SubType(){

        SuperType.call(this); 
        }

SubType.prototype=new SuperType(); 

Yes, there are differences. 是的,有差异。

In Segment 1, the subclass SubType does not call the constructor of SuperType so it never gets executed. 在段1中,子类SubType不会调用SuperType的构造函数,因此它永远不会执行。 Segment 1 is not a correct general purpose way to inherit from another object. 段1不是从另一个对象继承的正确通用方法。

In Segment 2, the subclass SubType does call the constructor of SuperType so the statement this.color=["blue","yellow"]; 在段2中,子类SubType确实调用了SuperType的构造函数,因此语句this.color=["blue","yellow"]; gets executed, but the prototype is not set appropriately so any prototype items that SuperType might have had are not inherited. 被执行,但是原型设置不当,因此不会继承SuperType可能拥有的任何原型项。 Segment 2 is not a correct general purpose way to inherit from another object. 段2不是从另一个对象继承的正确通用方法。

Segment 1 would work properly if there was no code in the SuperType constructor (not the case in your example). 如果SuperType构造函数中没有代码,则段1将正常工作(在您的示例中不是这种情况)。 As you show it, because the SuperType() constructor is not called, this.color would only be in the prototype and thus the same array would be shared by all instances which is generally NOT what you want. 如您所示,由于未调用SuperType()构造函数,因此this.color仅在原型中,因此所有实例将共享同一数组,这通常不是您想要的。 Calling the constructor properly would give every instance it's own copy of this.color , not a shared copy. 正确调用构造函数将为每个实例提供this.color的自己副本,而不是共享副本。

Segment 2 would work properly if nothing was added to the SuperType prototype and there are no constructor arguments for SuperType (happens to be the case in your example, but not a good general practice). 如果没有向SuperType原型添加任何内容并且没有SuperType构造函数参数,则第2部分将正常工作(在您的示例中可能是这种情况,但不是很好的常规做法)。

Neither is a good general purpose way of doing things. 通用的工作方式也不是。


Your last option is the proper general purpose way to do things because it both inherits from the prototype AND it executes the constructor of the inherited object. 最后一个选择是正确的通用处理方式,因为它既从原型继承,又执行继承对象的构造函数。


The most general purpose way also passes any constructor arguments to the inherited object using .apply(this, arguments) like this and initializes its own prototype and sets it's constructor property. 最通用的方法还使用.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() {};

If you are willing to only support IE9 and above, then you should change this line: 如果您只支持IE9及更高版本,则应更改以下行:

SubType.prototype = new SuperType();

to this: 对此:

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

This avoids calling the SuperType() constructor in order to just get an object to use for the prototype. 这避免了为了获得用于原型的对象而调用SuperType()构造函数。 In most cases this really doesn't matter, but in cases where the constructor has side effects outside of just initializing it's own properties, it can matter. 在大多数情况下,这确实无关紧要,但是在构造函数具有仅初始化其自身属性之外的副作用的情况下,这很重要。

In segment 1 the prototype gets set correctly but the constructor function of SuperType never gets called. 在第1部分中,原型已正确设置,但从未调用SuperType的构造函数。

At the start of segment 2 the constructor function of the SuperType gets called but the prototype is not set. 在第2段的开头,将调用SuperType的构造函数,但未设置原型。

The last example is correct because it sets up the prototype correctly as well as calls the SuperType 's constructor function. 最后一个示例是正确的,因为它可以正确设置原型并调用SuperType的构造函数。

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

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

SubType.prototype = new SuperType();

you should not set prototype inheritance with 你不应该设置原型继承

 SubType.prototype=new SuperType (); 

because there can be problems. 因为可能会有问题。

if you do that like this, the prototype of SubType would also inherit the property color as own property of the SubType prototype, because the constructor is worked through. 如果您这样做,SubType的原型也将继承属性color作为SubType原型的自己的属性,因为构造器已完成工作。 Every new instance of subType has then a reference to the color property in the prototype and is not an own property of the instance itself, this is finally not what you want because you only want to inherit the prototype. 然后,每个subType的新实例都具有对原型中color属性的引用,而不是实例本身的自身属性,这最终不是您想要的,因为您只想继承原型。 the luck is that after calling the super constructer every instance gets an own color property , but the color property is still also defined in the prototype. 幸运的是,在调用超级构造函数之后,每个实例都获得了自己的color属性,但是color属性仍然在原型中也定义了。 there is no need 没有必要

so to really inherit only the prototype you should use Object.create or do a workaround like this. 因此,要真正只继承原型,您应该使用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;

second way - better way - because no if Statement in the constructor is needed 第二种方法-更好的方法-因为不需要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 try the following - this will show a problem when people forget to call the super constructor and do inheritation with ...prototype=new constructor @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