Object.create changes prototype.constructor to parent constructor, but upon child instantiation, child constructor runs

烂漫一生 提交于 2020-01-11 06:49:15

问题


I've created an example to illustrate:

// 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') } */

So note how inheritance mostly worked as expected, cat inherited the method 'walk' from its parent dog class, and adding further methods to the child class such as meow works as expected. However, when I create an instance of cat, the constructor for cat runs, whereas cat.prototype.constructor points to the constructor "inherited" from dog.

Isn't the purpose of object.prototype.constructor to allow us to modify the constructor of an object after the object has been declared without wiping out the prototype for the object? In the above example, shouldn't the constructor stored in cat.prototype.constructor point to the same constructor that runs when creating a cat object? Does this apparent ambiguity have something to do with how in this source code this statement is run:

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

回答1:


The constructor property is just a simple property of the prototype object. There is nothing magically happening with it behind the scenes. It's a property that can be overridden and reset, but it doesn't affect anything else.

So when you do this:

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

you are overriding the entire prototype property of the function cat with a complete new object derived from the prototype object of animal. But since the constructor property is just a normal property of the prototype object, it will get overridden as well.

And yes, when implementing inheritance, the line

Class.prototype.constructor = Class;

is commonly added to restore the constructor property to its original value and to kind of undo the "damage" that was done by this inheritance pattern.

So in your case, you would need to add the following line:

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



回答2:


Think about the line:

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

Object.create(animal.prototype) will simply return an object that has no properties itself but whose prototype is given by animal.prototype. Therefore looking up the constructor property on this object will simply return the value held in animal.prototype.constructor.

Since the above line is assigning a reference to this newly created object to cat.prototype (and hence overwriting whatever was previously held in cat.prototype), of course you'd expect cat.prototype.constructor to be equal to animal.prototype.constructor.

As you mentioned above, you can side-step this 'issue' using something like:

cat.prototype.constructor = cat;

reference for Object.create(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create



来源:https://stackoverflow.com/questions/20830449/object-create-changes-prototype-constructor-to-parent-constructor-but-upon-chil

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!