简体   繁体   English

JavaScript原型继承案例

[英]JavaScript prototype inheritance cases

Could someone explain the difference between following inheritance implementations: 有人可以解释以下继承实现之间的区别:

function Parent(name) {
    this.name = name;
    this.parentFoo = function() {
       //...
    }
}

function Child() {
    this.additional = true;
    Parent.apply(this, arguments); // Is it for copying parent fields to child object?
}

Child.prototype = Object.create(Parent.prototype);

and

function Parent(name) {
    this.name = name;
}

Parent.prototype.parentFoo = function() {
    //....
}

function Child() {
    this.additional = true;
    Parent.apply(this, arguments); // Is it for copying parent fields to child object?
}

Child.prototype = Object.create(Parent.prototype);

I mean what would be better to use, adding function to constructor directly or to prototype? 我的意思是,将功能直接添加到构造函数或原型中会更好用吗? I'm asking because 我问是因为

var childObj = new Child("Child name");
var parentObj = new Parent("Parent name");

childObj.foo();
parentObj.foo();

work well in both cases. 在这两种情况下都能正常工作。 Thank you! 谢谢!

In the first snippet, you're not storing your methods in the Parent's prototype, so cloning Parent 's prototype for the Child class isn't doing anything. 在第一个代码段中,您没有将方法存储在Parent的原型中,因此为Child类克隆Parent的原型不会做任何事情。 You're still able to call parentFoo from the child instances because you're running the parent constructor with the child as its context with Parent.apply(this, arguments); 您仍然可以从子实例中调用parentFoo ,因为您正在运行带有父parentFoo的上下文的父构造函数,并使用Parent.apply(this, arguments); which runs 哪个运行

this.parentFoo = function() {
   //...
}

where the context this refers to the child instance. 在上下文this是指子实例。

I'm pretty sure re-defining and binding your methods in the constructor is not optimal. 我很确定在构造函数中重新定义和绑定您的方法不是最佳的。

In the second snippet, you're calling the constructor of the parent on the child, but you're not extending the parents prototype on the child class, so you won't be able to access the parentFoo method with instances of the child. 在第二个片段中,您将在子级上调用父级的构造函数,但不会在子级上扩展父级原型,因此您将无法使用子级实例访问 parentFoo方法。 You could fix that by adding the line from the first snippet: 您可以通过在第一个代码段中添加以下行来解决此问题:

 
 
 
  
  Child.prototype = Object.create(Parent.prototype);
 
  

Edit: The difference between the two cases is in the first one, you're not using prototypical inheritence. 编辑:这两种情况之间的区别是在第一种情况下,您没有使用原型继承。 You are cloning the parent prototype into the child's prototype, but you're not attaching any keys to the parent prototype. 您正在将父代原型克隆到子代原型中,但没有将任何密钥附加到父代原型上。 Instead you're redefining and directly binding each method to the instance in the parent constructor when you call Parent.apply(this, arguments); 相反,当您调用Parent.apply(this, arguments);时,您需要重新定义每个方法并将其直接绑定到父构造函数中的实例Parent.apply(this, arguments); in the child's constructor. 在孩子的构造函数中。

I believe the difference is the latter option (prototype) adds it to the signature of the object, but the former (using this) adds the function as a part of the memory footprint of the object. 我相信不同之处在于后一个选项(原型)将其添加到对象的签名中,而前一个选项(使用此选项)将功能添加为对象的内存占用量的一部分。 Therefore, in the latter option, the Parent object has parentFoo as part of it's definition, but in the former, each instance of the parent object has that function in memory. 因此,在后一个选项中,Parent对象将parentFoo作为其定义的一部分,但在前一个选项中,parent对象的每个实例在内存中都具有该功能。

See Learning JavaScript, especially class-like Constructor function and Property Inheritance through prototype/ proto chaining and References therein. 请参阅学习JavaScript,尤其是通过原型/ 原型和其中的引用学习类类构造函数和属性继承

Inheritance in JavaScript is usually done by Child.prototype=new Parent(); JavaScript中的继承通常由Child.prototype=new Parent(); .

// 'function' has "prototype" property by default.
// 'object' including 'function object' has "__proto__" property by default.

function Employee(){
   // Implicitly "this.__proto__=Employee.prototype;"
   this.name="empty";
   this.dept="general";
}
// By default, "Employee.prototype={__proto__:Object.prototype}"
// "(new Employee)={__proto__:Employee.prototype, name:"empty", dept:"general"}"
Employee.prototype.a="This is 'a' in Employee.prototype"; // Additional prototype 'a'.
// Then, "Employee.prototype={__proto__:Object.prototype, a:"Employee.prototype.a"}"


function Manager(){
   // Implicitly "this.__proto__=Manager.prototype;"
   this.reports=[];
}
// "(new Manager)={__proto__:Manager.prototype, reports:[]}"
Manager.prototype=new Employee;
// Then, "Manager.prototype={__proto__:Employee.prototype, name:"empty", dept:"general"}"

function WorkerBee(){
   // Implicitly "this.__proto__=WorkerBee.prototype;"
   this.projects=[];
}
// "(new WorkerBee)={__proto__:WorkerBee.prototype, projects:[]}"
WorkerBee.prototype=new Employee;
// Then, "WorkerBee.prototype={__proto__:Employee.prototype, name:"empty", dept:"general"}"


function SalesPerson(){
   // Implicitly "this.__proto__=SalesPerson.prototype;"
   this.dept="sales";
   this.quota=100;
}
// "(new SalesPerson)={__proto__:SalesPerson.prototype, dept:"sales", quota:100}"
SalesPerson.prototype=new WorkerBee;
// Then, "SalesPerson.prototype={__proto__:WorkerBee.prototype, projects:[]}"

function Engineer(){
   // Implicitly "this.__proto__=Engineer.prototype;"
   this.dept="engineering";
   this.machine="machine";
}
// "(new Engineer)={__proto__:Engineer.prototype, dept:"engineering", machine:""}"
Engineer.prototype=new WorkerBee;
// Then, "Engineer.prototype={__proto__:WorkerBee.prototype, projects:[]}"

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

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