Javascript继承:在设置原型时调用Object.create

时间:2013-02-23 20:09:00

标签: javascript prototype prototype-programming

我正在学习面向对象的Javascript的一些方面。我遇到了这个片段

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");

我的问题是:为什么这个代码片段会被使用 的Object.create(Person.prototype的)?我们不应该简单地用以下方式重置原型:

Employee.prototype = Person.prototype;

2 个答案:

答案 0 :(得分:8)

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

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

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

Employee.prototype = new Person;

但这需要实例化一个对象,这有点时髦 - 特别是如果你不想调用Person的构造函数。无论您是否想要这样,所有Employee实例都将继承未定义的“firstName”和“lastName”属性。

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

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

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

当然,如果您必须支持旧版浏览器,则无法使用Object.create。另一种方法是使用下划线或lodash等库中的clone / extend。或者是这个小小的舞蹈:

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

答案 1 :(得分:1)

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

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