The short answer, is that move
is not found on the Child
instance, but on the prototype it inherits from Human
.
Let's analyze your code.
const Child = function() {
this.name = "child"
}
const Human = function() {
this.move = "walking";
}
These are self explanatory, you make two constructor functions. They are unrelated (yet).
Child.prototype = new Human();
Child.prototype.constructor = Child;
This is the inheritance part. Child.prototype = new Human();
will create an instance of of Human
, and assign it to Child.prototype
, because the instance has a member move
, that gets assigned to Child.prototype
and you get what's essentially Child.prototype = { move: 'walking' }
or Child.prototype.move = 'walking'
(those aren't accurate, but close enough)
Then you assign Child
itself as the prototype.constructor
.
The reason you're seeing the weird behavior is that you expect move
to be an instance member, but it's a prototype member instead. A more significant drawback of this effect is that altering child.move
will alter it for all child instances at once, which is not what you'd expect from an instance member.
For this reason, it is not recommended to do inheritance by actually creating an instance, like you did, but using Object.create()
instead, like so:
Child.prototype = Object.create(Human.prototype);
Child.prototype.constructor = Child;
Additionally, your Child
function should be calling the parent constructor, to maintain the parent's logic and members. Like so:
const Child = function() {
Human.call(this); // call to parent constructor
this.name = "child";
}
Full code:
const Human = function() {
this.move = "walking";
}
const Child = function() {
Human.call(this);
this.name = "child"
}
Child.prototype = Object.create(Human.prototype);
Child.prototype.constructor = Child;
const child = new Child();
console.log(child);
Once you understand how prototype chains work, remember that ES6 classes were created to handle these situations more gracefully and with more readable code:
class Human {
constructor() {
this.move = "walking";
}
}
class Child extends Human {
constructor() {
super();
this.name = "child";
}
}