simonzack
simonzack

Reputation: 20948

Difference between Object.getPrototypeOf vs __proto__

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

Answers (5)

PHP Guru
PHP Guru

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

Willem van der Veen
Willem van der Veen

Reputation: 36660

Summary:

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.

Example:

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

Pacerier
Pacerier

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

Ilya Kharlamov
Ilya Kharlamov

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

loganfsmyth
loganfsmyth

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

Related Questions