Reputation: 20948
I know that the latter is non-standard. But Is there a difference between Object.getPrototypeOf
vs __proto__
? I'm investigating how the prototype chain in javascript works, and would like to be clear on this part.
Thanks.
Upvotes: 20
Views: 5345
Reputation: 1566
There are some good answers here but I didn't see anyone mention the difference in how they behave when getting the prototype of an object.
The biggest difference is that if object obj
does not have Object.prototype
in its prototype chain, or if __proto__
exists as a property elsewhere in its prototype chain, then you can't get its prototype with var prototype = obj.__proto__
because that won't reference Object.prototype.__proto__
. The work around is to use Object.prototype.__lookupGetter__('__proto__').call(obj)
.
Another difference is that Object.getPrototypeOf() throws in old browsers if you pass it a primitive value. However that behavior was changed in ES6 to only throw if passed null
or undefined
, same as Object.prototype.__proto__
in modern browsers. Now in the case of a primitive, they both return its wrapper object's prototype.
Also worth noting is that Object.prototype.__proto__
was implemented differently in different browsers before it was eventually standardized. That and it is deprecated which means it could be removed at any time.
In Conclusion:
In modern browsers, there is no difference in how they get the prototype of an object as long as you have a proper reference to Object.prototype.__proto__
when accessing an object's __proto__
property. That and Object.prototype.__proto__
is deprecated and could be removed at any time, so don't use it.
Upvotes: 0
Reputation: 36660
In javascript The __proto__
property of an object and the Object.getPrototypeOf()
method are both ways to access the prototype of an object. They both give us access to a reference of the prototype property.
What is the difference then?
Because __proto__
is simply a property of an object and was put there back in the day to access the prototype of an object. __proto__
is now deprecated and there is a chance that certain JS engines don't support this property anymore. Object.getPrototypeOf()
and Object.setPrototypeOf()
are the function which now should be used in order to retrieve a prototype.
function Dog (name) {
this.name = name;
}
Dog.prototype.bark = function () { console.log('woof'); };
let dog = new Dog('fluffie');
// DON'T:
// Old method using __proto__ deprecated!
console.log(dog.__proto__);
// DO:
// Using the newer getPrototypeOf function
console.log(Object.getPrototypeOf(dog));
// What about climbing up the prototype chain like this?
console.log(dog.__proto__.__proto__);
// We can simply nest the Object.getPrototypeOf() method calls like this:
console.log(Object.getPrototypeOf(Object.getPrototypeOf(dog)))
Upvotes: 0
Reputation: 89763
Proxy treats ≪__proto__≫ as a get:
_ = new Proxy({}, {
get:z=>console.log('a'),
getPrototypeOf:z=>console.log('b'),
});
_.__proto__/*a*/
—and ≪getPrototypeOf≫ as a getPrototypeOf:
_ = new Proxy({}, {
get:z=>console.log('a'),
getPrototypeOf:z=>console.log('b'),
});
Object.getPrototypeOf(_)/*b*/
Upvotes: 5
Reputation: 3932
Initially, __proto__
was a Mozilla-only hack in early versions of Mozilla browsers (Firefox prior to 3.5). It was codified in the ECMAScript 3.1 only in 2008.
One difference is that __proto__
can be changed (a bad design practice though) while getPrototypeOf
is a reading function.
var parentObject = {"parentKey" : "parentValue"};
var childObject = {"childKey" : "childValue"};
childObject.__proto__ = parentObject;
console.log(childObject.parentKey); // parentValue
Object.getPrototypeOf(childObject) = {"parentKey" : "newValue"};
// ReferenceError: Invalid left-hand side in assignment
Another difference is how they handle the unlikely case of a name conflict:
var myObject = { __proto__ : "conflicts", getPrototypeOf : function () {return "does not conflict"} };
console.log( myObject.getPrototypeOf() ); // "does not conflict"
// all objects inherit from Object.prototype, not Object, so there is no conflict
console.log( Object.getPrototypeOf(myObject) ) // Object {}
console.log( myObject.__proto__ ); // Object {}, the value "conflicts" is lost
Upvotes: 8
Reputation: 161637
From MDN:
Object.getPrototypeOf() is the standard implementation of the old and deprecated object.__proto__ property. However it is a read-only method.
So basically they accomplish the same thing if you are reading the value, except __proto__
is non-standard. __proto__
also potentially lets you set the prototype of an existing object, but generally that's not a good idea, so the standard now would be to use a constructor function or Object.create
to create an object with a specific prototype. That said, the ES6 spec also defines a setPrototypeOf
for setting the prototype of an object as well, though for performance reasons, it's best to avoid that unless explicitly necessary.
Upvotes: 22