While reading on Javascript's prototypes I encountered this behaviour I can't explain. I am testing this in chrome's console (which is V8).
var fruit = {taste:'good'};
var banana = Object.create(fruit);
console.log(banana.taste); //"good"
console.log(banana.__proto__); //Object {taste: "good"}
console.log(Object.getPrototypeOf(banana)); //Object {taste: "good"}
So far everything is as expected. However if I do this:
var drink = Object.create(null);
Object.defineProperty(drink, 'taste', {value:"nice"});
var coke = Object.create(drink);
console.log(coke.taste); //"nice"
console.log(coke.__proto__); //undefined
console.log(Object.getPrototypeOf(coke)); //Object {taste: "nice"}
then coke.__proto__ === undefined
. Why is it undefined
in the second case?
I once opened an issue for this behavior, but it was closed as standards-compliant behavior. According to the issue's close reason:
This is working as specified. ES6
__proto__
is a getter defined on Object.prototype. For an object that doesn't have that in its prototype chain it is not accessible (just like, say, hasOwnProperty isn't). You need to use Object.getPrototypeOf instead.
This is indeed true: ES6 section B.2.2.1 defines Object.prototype.__proto__
; therefore, the __proto__
property is inherited from Object.prototype
. However, your drink
object was created with Object.create(null)
, so it doesn't have Object.prototype
in its prototype chain.
An object always has internal knowledge to its prototype, stored in its [[Prototype]] internal slot. The __proto__
property is a way to access that internally-known prototype through code. An object's lack of a __proto__
property does not affect its [[Prototype]] slot, which still exists.
To be perfectly clear: coke
does have a prototype (stored in [[Prototype]]), and that prototype is the object drink
. You can see this with Object.getPrototypeOf(coke)
. However, that is the entire prototype chain, because the prototype of drink
is null
. Therefore, coke
can't inherit __proto__
from Object.prototype.__proto__
because it doesn't have Object.prototype
in its prototype chain.