Object.create changes prototype.constructor to parent constructor, mais lors de l'instanciation enfant, le constructeur enfant s'exécute

J'ai créé un exemple pour illustrer:

// this is the parent class function animal() { console.log('animal constructor') } // allow animals to walk animal.prototype.walk = function() { console.log('animal walking') } // create child class function cat() { console.log('cat constructor') } // cat inherits from animal cat.prototype = Object.create(animal.prototype); // let cats meow cat.prototype.meow = function() { console.log('meow') } // create a cat object var myCat = new cat(); /* output: cat constructor */ // yet, the constructor that ran is different than what the prototype for cat reports console.log(cat.prototype.constructor); /* output: function animal() { console.log('animal constructor') } */ 

Donc, notez comment l'héritage fonctionnait le plus souvent comme prévu, le chat a hérité de la méthode «promenade» de sa classe de chien parent, et ajouter d'autres méthodes à la classe enfant, comme le miau, fonctionne comme prévu. Cependant, lorsque je crée une instance de chat, le constructeur pour chat fonctionne, alors que cat.prototype.constructor pointe vers le constructeur "hérité" du chien.

N'est-il pas le but de object.prototype.constructor de nous permettre de modifier le constructeur d'un objet après que l'objet a été déclaré sans effacer le prototype de l'objet? Dans l'exemple ci-dessus, le constructeur ne doit-il pas stocker dans cat.prototype.constructor pointer vers le même constructeur qui s'exécute lors de la création d'un objet de chat? Est-ce que cette ambiguïté apparente a quelque chose à voir avec la façon dont dans ce code source cette instruction est exécutée:

 // Enforce the constructor to be what we expect Class.prototype.constructor = Class; 

La propriété constructor n'est qu'une propriété simple de l'objet prototype. Il n'y a rien de magique dans les coulisses. C'est une propriété qui peut être annulée et réinitialisée, mais elle n'affecte rien d'autre.

Donc, lorsque vous faites ceci:

 cat.prototype = Object.create(animal.prototype); 

Vous dépassez la propriété prototype entière de la fonction cat avec un nouvel objet complet dérivé du prototype objet d' animal . Mais puisque la propriété du constructor n'est qu'une propriété normale de l'objet prototype , elle sera également remplacée.

Et oui, lors de la mise en œuvre des héritages, la ligne

 Class.prototype.constructor = Class; 

Est généralement ajouté pour restaurer la propriété du constructor à sa valeur d'origine et pour désabonner le "dommage" qui a été fait par ce modèle d'héritage.

Donc, dans votre cas, vous devriez ajouter la ligne suivante:

 cat.prototype = Object.create(animal.prototype); cat.prototype.constructor = cat; // <---- add this 

Pensez à la ligne:

 cat.prototype = Object.create(animal.prototype); 

Object.create(animal.prototype) tout simplement un objet qui n'a pas de propriétés, mais dont le prototype est donné par animal.prototype . Par conséquent, rechercher la propriété constructor sur cet objet renverra simplement la valeur retenue dans animal.prototype.constructor .

Puisque la ligne ci-dessus attribue une référence à cet objet nouvellement créé à cat.prototype (et, par conséquent, cat.prototype tout ce qui était précédemment détenu dans cat.prototype ), bien sûr, vous vous attendez à ce que cat.prototype.constructor soit égal à animal.prototype.constructor .

Comme vous l'avez mentionné ci-dessus, vous pouvez contourner ce «problème» en utilisant quelque chose comme:

 cat.prototype.constructor = cat; 

Référence pour Object.create (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create