为什么函数的旧构造函数被调用?

时间:2017-09-28 03:04:44

标签: javascript prototype

我的理解是,当您将函数的函数原型更改为指向不同的对象时,新原型的构造函数将指向新对象的原型构造函数。

来自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

  

当执行代码new Foo(...)时,会发生以下情况:

     

1)创建一个新对象,继承自Foo.prototype。

     

2)使用指定的参数调用构造函数Foo,   并将此绑定到新创建的对象。新的Foo是等价的   到新的Foo(),即如果没有指定参数列表,则调用Foo   没有争论。

     

3)构造函数返回的对象成为结果   全新的表达。如果构造函数没有   显式返回一个对象,使用在步骤1中创建的对象   代替。 (通常构造函数不返回值,但它们可以   如果他们想要覆盖正常的对象创建,请选择这样做   过程。)

此外,来自https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance

  

在继续前行之前,我们还需要做一件事。添加完最后一个   line,Teacher.prototype的构造函数属性现在等于   Person(),因为我们只是将Teacher.prototype设置为引用一个对象   从Person.prototype继承其属性!尝试保存你的   代码,在浏览器中加载页面,然后输入   将Teacher.prototype.constructor放入控制台进行验证。

在我的示例中,就我所知,customPrototype从Object.prototype继承了它的属性,所以一旦我将Person.prototype重新分配给它,它也应该更改构造函数。并记录它我发现构造函数确实发生了变化!

// Some custom object to inherit  
var customPrototype = {
  name: "XYZ"
};

// Person has its prototype object pointing to Object.prototype
var Person = function() {  
  this.name = "Not XYZ";
};

// Prints function() {this.name = "Not XYZ";}
console.log(Person.prototype.constructor);

// Change Person prototype to point to the custom prototype object
Person.prototype = customPrototype;

// Prints function Object() { [native code] }
console.log(Person.prototype.constructor);

var p = new Person();

// Prints Not XYZ
console.log(p.name);

鉴于上面的示例,我期望打印XYZ的姓氏,因为没有任何内容会被customPrototype对象覆盖。

我错过了什么?为什么在(我认为)它应该调用Object.prototype.constructor时它仍然调用Person函数?

1 个答案:

答案 0 :(得分:2)

Prototype.constructor与对象初始化无关。当您想要创建对象时,调用实际调用new Person()函数的Person,将对象作为上下文(this)传递给函数并返回该对象。无论你拥有什么样的原型,都会调用Person函数。因为在此功能中,您将属性name设置为Not XYZ,它将具有该值。它使用相同的名称隐藏prototype属性。如果您要从对象中删除此属性并尝试再次访问name,您将获得原型。

var customPrototype = {
  name: "XYZ"
};

var Person = function() {  
  this.name = "Not XYZ";
};

Person.prototype = customPrototype;
var p = new Person();
console.log(p.name);
delete p.name;
console.log(p.name);

我们设置prototype.constructor以保持对象的精确构造,如果我们想根据对象的类型进行一些检查。

Person类型的对象实现复制逻辑。

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

Person.prototype.copy = function() {
  return new this.constructor(this.name); // Access by `constructor` property, it is not necessary to call directly `Person`
}

const person = new Person('Bob');
console.log(person.name);
const secondPerson = person.copy();
console.log(secondPerson.name);
console.log(person === secondPerson);