【问题标题】:JavaScript Objects get overwritten when using prototypingJavaScript 对象在使用原型设计时被覆盖
【发布时间】:2012-07-17 16:10:07
【问题描述】:

我有一个 Pers(on) 和一个从 Pers 派生的 Employee。

Pers = function(options){
  this.Name;
  this.ID;
  this.init = function(options){
    this.Name=options.Name;
    this.ID=options.ID;
  }
}

Employee = function(options){
  this.Sal;
  this.init = function(options){
    this.Sal=options.Sal;
    this.__proto__.init(options);
  }
  this.init(options);
}

Employee.prototype=new Pers();

现在当我创建新对象时...

var o=new Employee({Name:"Nik",ID:"1",Sal:100});
var p=new Employee({Name:"Tanja",ID:"2",Sal:200});

并提醒他们的名字,我会得到两次“Tanja”。

有人有想法吗?

【问题讨论】:

  • 很确定你不应该再使用__proto__了。

标签: javascript object prototype


【解决方案1】:
this.__proto__.init(options);

将调用原型上的init方法,原型本身为this,导致您修改原型。试试

this.__proto__.init.apply(this, [options]);

编辑

为避免__proto__,您可以在隐藏原型 init 函数之前保存对它的引用:

Employee = function(options){
  this.Sal;
  var protoInit = this.init;
  this.init = function(options){
    this.Sal=options.Sal;
    protoInit.apply(this, [options]);
  }
  this.init(options);
}

【讨论】:

  • call(this, options) 在这种情况下可能更好
【解决方案2】:

您在错误的范围内调用 init。试试这样的。

function Person(opt) {
    this.name = opt.name;
    this.id = opt.id;
}

function Employee(opt) {
    Person.call(this, opt);
    this.sal = opt.sal;
}

Employee.prototype = Object.create(Person.prototype, {});

您现在可以设置Person.prototypeEmployee.prototype 的属性,它们的行为应该符合预期。

这避免了使用不推荐使用的 hacky 属性 (__proto__) 并且应该更清晰。 Object.create 用于使用超级构造函数的原型创建实例,而无需实际调用超级构造函数(无需调用init)。您可以在执行此操作时包含半标准属性定义,例如 superconstructor,就像许多库的 inherits 实现一样。

【讨论】:

  • 这不起作用,当我创建新对象时: var o=new Employee({name:"Nik",id:"1",sal:100}); var p=new Employee({name:"Tanja",id:"2",sal:200}); o.name 将找不到。我做错了什么?
  • 在没有init 的情况下急于重写,我犯了和你一样的错误。答案已编辑。