This is actually the expected behavior. If you want to understand why, here we go...
Consider the following schema, available in the excellent book Exploring ES6 by Dr. Axel Rauschmayer.

Before to go on, here is an important rule: in JavaScript, when you create an instance of a "class", this instance will reference the prototype property of its constructor through its dunder proto (__proto__
or [[Prototype]]
).
Top left
In your example, Employee
and PermanentEmployee
are constructor functions. Like any function in JavaScript, they are instances of Function
and they use Function.prototype
.
var Employee = function(name) {
this.name = name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
console.log(typeof Object.getPrototypeOf(Employee)); // ES5
console.log(typeof PermanentEmployee.__proto__); // ES6
console.log(Object.getPrototypeOf(Employee).constructor); // ES5
console.log(PermanentEmployee.__proto__.constructor); // ES6
Top right
When you write Employee.prototype.getName
or PermanentEmployee.prototype.getSalary
, you are actually adding new properties to the prototype property of Employee
and PermanentEmployee
. But Employee.prototype
and PermanentEmployee.prototype
are instances of Object
and use Object.prototype
.
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
console.log(typeof Employee.prototype);
console.log(typeof PermanentEmployee.prototype);
console.log(Employee.prototype);
console.log(PermanentEmployee.prototype);
Since PermanentEmployee.prototype
is a simple object, this is not reasonable to do so: PermanentEmployee.prototype = employee
.
When you do that, you override the prototype. To make a basic comparison, look at this example with an object literal:
var obj = {
foo: 'Foo'
};
obj.bar = 'Bar';
console.log(obj);
obj = 'Baz';
console.log(obj);
obj = {
foo: 'Foo',
bar: 'Bar',
baz: 'Baz'
};
console.log(obj);
You should keep this in mind when you play with prototypes...
Bottom right
In JavaScript, there are several strategies to create a "pure" object (functions and arrays are objects too...). You can:
- Use an object literal:
{}
- Use a constructor:
new Object()
- Use
Object.create()
In your example, you are using constructors. Therefore, your instances will use the prototype properties of your constructors, which themselves use the prototype property of Object
. This is how the prototype chain works!
var Employee = function(name) {
this.name = name;
}
Employee.prototype.getName = function() {
return this.name;
}
var PermanentEmployee = function(annualSalary) {
this.annualSalary = annualSalary;
}
PermanentEmployee.prototype.getSalary = function() {
return this.annualSalary;
}
var employee = new Employee("Mark");
console.log(Object.getPrototypeOf(employee)); // ES5
console.log(employee.__proto__.constructor); // ES6
console.log(Object.getPrototypeOf(Object.getPrototypeOf(employee))); // ES5
console.log(employee.__proto__.__proto__.constructor); // ES6
But of course, if you have completely overriden your prototype somewhere, you break the prototype chain and it will not work as expected...