javascript - 为什么即使我们在使用 new 关键字创建对象时手动将其更改为另一个构造函数,也会执行 A 对象的构造函数?

标签 javascript object

function Animal() { console.log("Animal")}
function Bird() { console.log("Bird")}
function Dog() { console.log("Dog")}

Bird.prototype = Object.create(Animal.prototype);
Dog.prototype = Object.create(Animal.prototype);


 duck = new Bird();
 beagle = new Dog();

在上面的代码中——我们从 Animal 继承了 Bird 和 Dog。 他们的原型(prototype)将是动物。所以默认情况下 Bird.constructor 将指向 Animal 构造函数。

当执行 new Bird() 时。我希望“Animal 登录到控制台”,但 Bird 已登录。由于构造函数是 Animal。应该执行动物构造函数吗?纠正我的理解

最佳答案

您将继承与构造函数调用混淆了。当你说:

duck = new Bird();

您正在对Bird 构造函数进行显式 调用,因此Bird 当然会触发。


虽然 Object.create() 是一种使一个对象从另一个对象继承的简便方法,但您仍然必须手动设置构造函数链。理解这一点的一个好方法是当两个构造函数都接受参数时(如下所示)。

查看内联评论:

function Animal(gender) {
  // The argument allows the instance property to initialize.
  // gender will be a property of Animal and will be inherited
  // by anything that inherits from Animal later. But, that
  // doesn't change the fact that the Animal constructor
  // must be called and passed the gender for the Animal
  // to be properly initialized.
  this.gender = gender;
  
  // Get the caller of this function (non-standard technique - just used for demo).
  // If the caller is null, it means that Animal was called directly. If not,
  // we can get the name of the calling function:
  var caller = Animal.caller ? Animal.caller.name : "Animal";
  
  // Report of newly constructed Animal
  console.log("Animal is a " + this.gender + ". (called by: " + caller + ")");
}


function Bird(gender, canFly) {   
  // Because a bird inherits from an Animal, you have
  // to manually ensure that when a new Bird is created
  // the Animal constructor gets called. You can see 
  // why this is necessary as we have a situation where
  // the prototype's constructor is expecting an argument
  // that we've received when the constructor of the 
  // derived object was called. We certainly don't want
  // to have to rewrite the code that sets the gender, so
  // we call the prototype's constructor and pass it what
  // it is expecting and allow it to do some of the object
  // initialization for us:
  Animal.prototype.constructor.call(this, gender);
  
  // Arguments meant for the current constructor are handled 
  // in the current constructor
  this.canFly = canFly
  
  // The inherited properties are available:
  console.log("Bird is a " + this.gender + " and it can fly: " + this.canFly);
}

// This just causes Bird to inherit from Animal. This alone
// doesn't cause the Animal constructor to fire when new Bird()
// is executed.
Bird.prototype = Object.create(Animal.prototype);

// By using a different prototype, we have wiped out the native
// constructor so we will reset just the contstructor so that
// constructions of Bird work properly
Bird.prototype.constructor = Bird;

// Just a test to show that making an Animal properly
// requires that the Animal constructor be called and
// passed a gender.
console.log("--- Creating New Animal ---");
var generic = new Animal("male");

// You are explicitly invoking the Bird constructor here.
// It's going to fire that function. That function, in turn,
// is configured to invoke the prototype object's constructor.
// The gender property will be handled by the Animal constructor
// and the canFly will be handled by the Bird constructor.
console.log("--- Creating New Bird ---");
duck = new Bird("female", false);

// ************************************************

function Falcon(gender, canFly, trained){
  // We'll pass the arguments needed by the parent object to it
  Bird.prototype.constructor.call(this, gender, canFly);
  
  // And set current instance properties right here
  this.trained = trained;

  console.log("Bird is a " + this.gender + ", can fly: " + this.canFly + " and is trained: " + this.trained);
}

Falcon.prototype = Object.create(Bird.prototype);

// By using a different prototype, we have wiped out the native
// constructor so we will reset just the contstructor so that
// constructions of Falcon work properly
Falcon.prototype.constructor = Falcon;

console.log("--- Creating New Falcon ---");
let f = new Falcon("female", true, false);

关于javascript - 为什么即使我们在使用 new 关键字创建对象时手动将其更改为另一个构造函数,也会执行 A 对象的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53470033/

相关文章:

javascript - 根据偶数/奇数索引将数组转换为对象

javascript - 为什么在 Typescript 中实例化类时我的代码会卡住?

c++ - 为什么我的银行管理系统不能正常工作?

javascript - 如何使用 AngularJS 将字母列排序添加到表中

javascript - 使用 jQuery 的定期 ajax 请求超时

java - 如何将Object转换为 "original"类型

Java:从类创建对象

javascript - 计算奇偶数函数问题

javascript - 以express方式发送post请求时超出了最大调用堆栈大小

javascript数学函数: Right now it forms a circle,我需要做一个半圆