I'm currently trying to understand the constructor
property in javascript.
Just a heads up, I understand changing the properties of builtin should be avoided, I'm playing around with it because I want to better understand the underlying principles.
I tried to change the default constructor
property of []
(i.e. default constructor for array objects)
[].__proto__.constructor === [].constructor; // true
[].constructor = function A(){}; // attempts to reset the constructor property to a new function
[].constructor; // prints ƒ Array() { [native code] }, which indicate the attempt failed
But when I checked the property descriptor of [].constructor
Object.getOwnPropertyDescriptor([].__proto__, 'constructor');
which prints
{value: ƒ, writable: true, enumerable: false, configurable: true}
So the [].__proto__.constructor
property is writable
?
So I tries to set the constructor
property via [].__proto__
, it succeeded
[].__proto__.constructor = function B(){};
[].__proto__.constructor; // prints: ƒ B(){}, which indicate the attempt succeded
Why changing the constructor
property via []
failed but via [].__proto__
succeeded? Even though [].constructor === [].__proto__.constructor
returned true
.
This is due to property shadowing on the prototype chain. When you execute
[].constructor = ...;
this creates an instance property on the array that shadows the class prototype constructor. However, since Array.prototype
already has its own constructor
property, executing
[].__proto__.constructor = ...;
overwrites the constructor on Array.prototype
.
You can confirm this behavior by actually storing the array instance and looking closer at its prototype chain:
Below verifies that the assignment actually creates an own property on array1
which shadows the inherited property from Array.prototype
.
function A(){}
var array1 = [];
array1.constructor = A;
console.log(array1.constructor === A);
console.log(array1.__proto__.constructor === Array);