Почему конструктор объекта A выполняется, даже если мы меняем его вручную на другой конструктор при создании объектов с использованием нового ключевого слова? - PullRequest
0 голосов
/ 25 ноября 2018
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();

В приведенном выше коде - мы наследуем Bird и Dog от Animal.Их прототипом будет животное.Таким образом, по умолчанию Bird.constructor будет указывать на конструктор Animal.

Когда выполняется новый Bird ().Я ожидаю, что "Животное будет зарегистрировано на консоли", но Bird зарегистрирован.Так как конструктором является Animal.Конструктор животных должен быть выполнен правильно?Поправь мое понимание

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Оператор

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

делает объект-прототип конструктора Bird объектом new , собственный прототип которого является Animal prototype ,не сам конструктор Animal.

Таким образом,

duck = new Bird()

создает новый объект, конструктор которого Bird, прототипом которого является прототип Bird, который, в свою очередь, наследуется отAnimal prototype.

Таким образом, ваш Animal прототип может иметь метод с именем eat(), поэтому вызов

duck.eat("fish")

будет фактически вызовом eat() метод на Animal прототипе.Зачем?Да, у объекта duck нет никакого свойства "есть", а у прототипа Bird нет, но у есть свойство "есть" у прототипа Animal.

0 голосов
/ 25 ноября 2018

Вы путаете наследование с вызовами конструктора.Когда вы говорите:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...