省略 prototype.constructor 更改原型链

Omitting prototype.constructor changes prototype chain

我试图了解 JavaScript 中的继承,并且我已经看到 JavaScript 中有不同的方法来实现继承。一种这样的方法基于 Mozilla 站点的示例,该示例执行类似于以下代码的操作:

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

Person.prototype.getName = function() {
  return this.name;
}

Person.prototype.setName = function(name) {
  this.name = name;
}

function Employee(name, Id) {
  Person.call(this, name);
  this.Id = Id;
}

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

Employee.prototype.getId = function() {
  return this.Id;
}

Employee.prototype.setId = function(Id) {
  this.Id = Id;
}

var andrew = new Employee("Andrew", "123");

我知道这段代码非常基础,我真的不需要定义 getter 和 setter。我添加它们只是为了表明我可以添加到每个原型对象。在大多数情况下,我理解这段代码的作用。

当我看到以下行时开始感到困惑:

Employee.prototype.constructor = Employee;

我了解到我们正在将 Employee.prototype 对象的构造函数 属性 设置为指向 Employee 构造函数。我已经阅读了该站点上的其他帖子,这些帖子说我可以省略这一行,实际上如果我这样做,一切都会按预期进行。但是......当我省略这一行时,我看到原型链发生了一些变化。 Employee 对象的 __proto__ 属性 现在指向具有以下方法的通用对象:getIdsetId。然后这个对象的__proto__ 属性指向Person.prototype对象。

所以我的问题是:

为什么当我省略 Employee.prototype.constructor = Employee 时,__proto__ 属性 指向一个具有我在 Employee.prototype 对象中设置的方法的通用对象,而不是Employee.prototype 对象本身?此外,getIdsetId 方法是如何附加到这个神秘的原型上的,是否会因此影响性能?

我已经从 Chrome 控制台附加了 console.logs 以显示 __proto__ 属性 手动设置构造函数 属性 然后省略它.

对象没有名字。因此,您在 __proto__ 旁边看到的是控制台 以某种方式 推断出的名称。显然,这种方式涉及 constructor 某种方式。

原型链没有变化,只是呈现给您的信息。 __proto__ 指的是 Employee.prototype 而不管 constructor 的值。


看看这个例子:

var foo = {};
console.log(foo); // Object {}

foo.constructor = function Foo() {};
console.log(foo); // Foo {}

foo这里没有变化,是一个普通的对象。但是,一旦 constructor 被设置,它就好像是 Foo.

的一个实例一样呈现

似乎 Chrome 只需要 constructor 属性 即可在控制台中显示对象的 Class 名称。
因此可以创建任何对象并简单地为其分配任何函数 constructor 属性。结果 - 您将在控制台中看到此名称:

var obj = { prop: 1 };
obj.constructor = function MyName() {};

将显示:

...the __proto__ property points to an generic object with the methods I set in the Employee.prototype object and not the Employee.prototype object itself?

你说的"generic object"Employee.prototype。您可以自己在 Chrome 中通过以下方式轻松测试:

  • 右键单击 __proto__: Object
  • 从菜单中选择“存储为全局变量”以创建 temp1 变量
  • 测试 temp1 == Employee.prototypetrue