【问题标题】:Javascript inheritance: calling Object.create when setting a prototypeJavascript 继承:设置原型时调用 Object.create
【发布时间】:2013-02-09 07:18:36
【问题描述】:

我正在学习面向对象的 Javascript 的某些方面。我遇到了这个sn-p

var Person = function(firstName, lastName)
{
  this.lastName = lastName;
  this.firstName = firstName;
};

Object.defineProperties(Person.prototype, {
  sayHi: {
    value: function() {
      return "Hi my name is " + this.firstName;
    }
  },
  fullName: {
    get: function() {
      return this.firstName + " " + this.lastName;
    }
  }
});

var Employee = function(firstName, lastName, position) {
  Person.call(this, firstName, lastName);
  this.position = position;
};

Employee.prototype = Object.create(Person.prototype);

var john = new Employee("John", "Doe", "Dev");

我的问题是:为什么这个 sn-p 使用 Object.create(Person.prototype)?我们不应该简单地重置原型:

Employee.prototype = Person.prototype;

【问题讨论】:

  • 从今天开始非常棒的answer
  • 哇。感谢那。收藏学习! :-)
  • No.

标签: javascript prototype prototype-programming


【解决方案1】:

我的猜测是,其目的是创建一个新对象,而不仅仅是来自 Person 的引用。

//create a new object with its prototype assigned to Person.prototype
Employee.prototype = Object.create(Person.prototype);

【讨论】:

    【解决方案2】:

    执行 Employee.prototype = Person.prototype 就像说“Employee is Person”而不是“Employee is a Person”。对任一原型的任何更改都将反映在两个类中。

    这是demonstration。显然我们不希望我们的 Person 工作,因为他们没有职位。

    所以在没有 Object.create 的情况下设置原型链的正确方法是:

    Employee.prototype = new Person;
    

    但这需要实例化一个对象,这有点奇怪——尤其是如果您不希望调用 Person 的构造函数。无论您是否想要,您的所有 Employee 实例都将继承未定义的“firstName”和“lastName”属性。

    在这种情况下,这没什么大不了的 - Employee 构造函数将在其自身上设置这些属性,这将取代从 Person 继承的属性。但是考虑this example。有人可能认为 freeTime 是 Person 的实例级属性,不会被复制,因为它不在原型上。另外,我们从未从 Employee 调用 Person 构造函数。并非如此——因为我们必须实例化一个对象,所以在 Employee 原型上设置了 freeTime

    因此,您可以做的最好和最干净的继承是通过 Object.create。如果要调用父类的构造函数,可以在子类的构造函数中显式调用。另一个好处是 Object.create 有第二个(可选的)参数来定义属性。所以你也可以这样做:

    Employee.prototype = Object.create(Person.prototype, {
      work: {
        value: function() {
          return this.fullName+" is doing some "+this.position+" stuff");  
        }
      }
    });
    

    当然,如果您必须支持旧版浏览器,则不能使用 Object.create。另一种方法是使用来自下划线或 lodash 等库的克隆/扩展。或者有这个小舞蹈:

    var subclass = function() { };
    subclass.prototype = Person.prototype;
    Employee.prototype = new subclass;
    

    【讨论】:

    • 为什么这是正确的方法?我的意思是,如果 Person 对象具有属性/字段(名字、姓氏)怎么办? Employee 的原型应该可以访问它吗?而且我还需要提供姓氏和名字,因为构造函数需要它们。
    • 更新了演示。
    • 我认为这里给出的例子很糟糕。我希望将freeTime 复制到子对象,因为它是在父构造函数中设置的,并且您应该从子构造函数中调用该构造函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    相关资源
    最近更新 更多