如何在javascript中继承基类属性并调用基类构造函数?

如何在javascript中继承基类属性并调用基类构造函数?,javascript,inheritance,prototypal-inheritance,Javascript,Inheritance,Prototypal Inheritance,假设我有一个Employee类: function Employee(name, age, salary) { this.name = name; this.age = age; this.salary = salary; } function Manager(name, age, salary, management_school_name) { ... } Manager.prototype = new Employee(); Manager.prototype.cons

假设我有一个
Employee
类:

function Employee(name, age, salary) {
  this.name = name;
  this.age = age;
  this.salary = salary;
}

function Manager(name, age, salary, management_school_name) {
  ...
}

Manager.prototype = new Employee();
Manager.prototype.constructor = Manager;
在上面的代码中,我想利用
Employee
封装
name
age
salary
的事实

那么,我应该如何处理重复的参数呢

function Employee(name, age, salary) {
  this.name = name;
  this.age = age;
  this.salary = salary;
}

function Manager(name, age, salary, management_school_name) {
  Employee.call(this,name,age,salary); //Call base constructor function
...
}
Manager.prototype = new Employee(); //Create prototype chain
Manager.prototype.constructor = Manager;
创建原型链的另一种方法是使用
Object.create

Manager.prototype = Object.create(Employee.prototype); //Create prototype chain
以下是Object.create在内部的实现方式:

function create(proto) {
  function F() {};      
  F.prototype = proto ;
  return new F();      
}
那么我们应该在什么时候使用
Object.create
newemployee()
来创建原型链呢


Object.create
没有任何用于创建对象的构造逻辑,而我们可以在
Employee
中包含构造逻辑,如
this.default=“default”
。在这种情况下,使用
newemployee()
Object.create
没有太大区别。但是如果我们需要完全避免构造逻辑,我们可以使用
对象。create

经理也是一名员工,那么为什么不这样做:

function Staff(name, age, salary) {
  this.name = name;
  this.age = age;
  this.salary = salary;
}

function Position(positionName, management_school_name) {
   this.positionName = positionName;
   this.managent_school_name = management_shool_name;
}

Staff.prototype.position = new Position();
您可以尝试以下方法:

Function.prototype.inherit = function(Parent) {
    this.prototype = Object.create(Parent.prototype)
    this.prototype.constructor = this
}
(保加利亚朗)


您还可以看到前面所述的演示

;最好不要创建父对象的实例来设置子对象的原型。要重新使用父构造函数,可以执行
Parent.call(this,args)在子对象中

为了更好的可读性,我喜欢使用arguments对象,当一系列函数在一个链中被调用时,函数可以去掉并改变与它们相关的部分。比如说

function Employee(args) {
  //name is mandatory
  if(typeof args.name === "undefined")
    throw new Error("Cannot create an Employee instance without passing a name.");
  this.name = args.name;
  //age is optional and default is 25
  this.age = (typeof args.age === "undefined")? 25:args,age;
  //optional, defaults to 2500
  this.salary = (typeof args.salary === "undefined")?2500:args.salary;
}

function Manager(args) {
  //re use Employee constructor
  Employee.call(this,args);
  //set Employee specific values same as Employee
}
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;

var m = new Manager({name:"Harry",age:33,salary:5000});

有关构造函数和原型的更多信息。

在上面的帖子中正确解释了您想要实现的功能。但下面的一行将解释为什么会这样

有两种方法可以向类(而不是函数类)添加公共属性和方法:

添加公共属性的方法1,添加到每个实例:

function MyClass(){
      this.publicProperty = 'public property'; 
}
添加公共属性的方法2,添加到原型,适用于所有实例:

MyClass.prototype.publicMethod = function(){
      console.log('public method');
}
如果要从
类继承,则需要继承所有公共属性和方法

继承使用方法1添加的属性和方法:

function MyDerivedClass(){
      MyClass.apply(this);
}
继承使用方法2添加的属性和方法:

MyDerivedClass.prototype = Object.create(MyClass.prototype);

希望这能有所帮助。

通常是这样做的吗?还是我的基本设计本身就不好?+1但是,如果我也需要原型中的数据呢?@thefourtheye:在这个问题中,这一行负责创建原型链:
Manager.prototype=new Employee()
@thefourtheye您使用的
Child.prototype=Object.create(Parent.prototype)
当您的父对象具有类似
this.someObject=[]
的实例变量时,所有子实例都将在原型上具有someObject,但如果我创建ben,然后jerry作为子对象并执行
ben.someObject.push(“来自ben的值”)
jerry.someObject将具有值[“value from ben”],因为子对象共享
someObject
成员。有关实例特定成员和共享原型成员的说明可在此处的介绍中找到:@learner您不应将Child.prototype设置为父实例,因为父实例特定成员是在Child.prototype上设置的,所有子实例将共享特定于实例的成员,见第四章的评论。充其量,您将立即对这些特定于实例的成员进行阴影处理,但在立即进行阴影处理的Child.prototype上定义成员是在浪费内存。您能解释一下吗?在我的示例中,我将您的经理和员工类合并为一个员工类。现在经理和员工也是员工,所以他们使用相同的信息:姓名、年龄、薪水。如果你想让一名员工成为经理,只需设置其职位原型。对不起我的英语!谢谢这是原型遗传还是伪古典遗传的例子?@learner,我想是的。长期以来,这是唯一的办法。最近有另一种方法来处理Object.create,但您需要添加一个init或构造函数来初始化特定于实例的成员,所以基本上可以归结为同一件事。原型和伪经典实际上是完全不同的。@学习者很感兴趣,在我回答您之后,您回答了自己的问题。你能告诉我区别吗?在我的理解和我所看到的使用模式中,子对象的原型被设置为父对象的浅层副本,并且在创建实例时使用构造函数或init函数来设置特定于实例的成员。代码看起来不同,因为您可以用数百种不同的方式来完成,但结果基本相同。我可能错了,如果你能表现出主要的差异,我会很高兴。