Consider the following javascript code
var a = Object.create(null);
a.foo = 1;
var b = Object.create(a);
console.log(b.foo); //prints 1
console.log(b.__proto__); //prints undefined
b.__proto__ = null;
console.log(b.__proto__); //prints null
console.log(b.foo); //prints 1
Can anyone explain how object b
is accessing the "foo" property of a
even after setting b.__proto__
to null? What is the internal link which is used to access the property of a
?
I tried searching through SO for possible explanations but couldn't find any explanation for this particular behaviour of Javascript.
The __proto__ property is a default property added to every object. This property points to the prototype of the object. The default prototype of every object is Object. prototype .
The __proto__ property of Object. prototype is an accessor property (a getter function and a setter function) that exposes the internal [[Prototype]] (either an object or null ) of the object through which it is accessed.
prototype while Object. create(null) doesn't inherit from anything and thus has no properties at all. In other words: A javascript object inherits from Object by default, unless you explicitly create it with null as its prototype, like: Object. create(null) . {} would instead be equivalent to Object.
prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype.
Your problem is that you are using the deprecated __proto__
property, which is a getter/setter on Object.prototype
- but your objects don't inherit from that, so it's undefined
at first and the assignment creates a standard property with the name __proto__
.
Use the proper Object.getPrototypeOf
/Object.setPrototypeOf
instead and the code will do what you expect:
var a = Object.create(null);
a.foo = 1;
var b = Object.create(a);
console.log(b.foo); // 1
console.log(Object.getPrototypeOf(b)); // {foo:1} - a
Object.setPrototypeOf(b, null);
console.log(Object.getPrototypeOf(b)); // null
console.log(b.foo); // undefined
Answer by @Bergi is correct. Here is in-depth answer what is happening in case of __proto__
var a = Object.create({});
var b = Object.create(a);
b.__proto__===a; //true
var c = Object.create(null);
var d = Object.create(c);
d.__proto__===c; //false..confusion
Object.hasOwnProperty.call(d,"__proto__"); //false as expected
Object.hasOwnProperty.call(b,"__proto__"); //false ?
Object.hasOwnProperty.call(Object,"__proto__"); //false
Object.hasOwnProperty.call(Object.prototype,"__proto__"); //true
Which means __proto__
is only present in Object.prototype
.
Object.getOwnPropertyDescriptor(Object.prototype,"__proto__")
//{enumerable: false, configurable: true, get: ƒ, set: ƒ}
__proto__
is a getter setter which should return internal link to object parent something like
get __proto__(){return this.hidden_internal_link_to_parent;}
Case b.__proto__
:- b
doesn't have __proto__
property so it goes through [[prototype]]
chain to a
, then to a
's parent and at last to Object.prototype
. Object.prototype
have __proto__
and it returns link of b
's parent which is a
.
Case d.__proto__
:- d
's link to Object.prototype
is broken (d --parent-->c and c--parent-->null). So d.__proto__
is undefined. But d
have internal link to c
which can be accessed by Object.getPrototypeOf(d)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With