nahelm
nahelm

Reputation: 1056

Object.create setting __proto__ but not prototype

I'm pretty new to using object.create instead of the classical js way to acheive prototypical inheritance.

In Chrome at least I was surprised to see the following code:

var baseObject = {
test : function(){
    console.log('Child');
}
}

var newObject = Object.create(baseObject);
newObject.test = function(){
console.log('Parent');
this.__proto__.test();
}
console.log(newObject);

newObject.test();

Produces this (simulating the output in web tools):

Object {test: function, test: function} 
    test: function (){
    __proto__: Object
        test: function (){
        __proto__: Object
Parent
Child 

So you see it's not setting prototype but instead only "__proto__", which I thought was discouraged in its use. You can see that in my code I'm able to properly inherit, and call the parent object, but only using "__proto__". Using "prototype" results in an error (undefined).

What's going on here? I figured object.create would set the "prototype" instead as that is the standard (or so I had assumed). Why is it populating and making me using "__proto__"

Upvotes: 5

Views: 1320

Answers (3)

Brandon
Brandon

Reputation: 39192

Object.create() sets the prototype for that particular object instance. prototype is a property on a constructor function that is the object automatically assigned as the [[Prototype]] for each instance created by using the new operator with that constructor function.

__proto__ is a non-standard way to access the [[Prototype]] for a particular instance. You can also call Object.getPrototypeOf(this) for a standard way to access the prototype.

Upvotes: 0

the system
the system

Reputation: 9336

No using __proto__ to set up your prototypal inheritance is discouraged because it's non-standard. That doesn't mean you can't use Object.create() to make a new object with a particular prototype object.

Objects do not have a .prototype property by default. You're confusing the .prototype object of a function.

So if I have a function like this:

function Foo() {

}

That Foo function object has a .prototype property that references an object that will be used as the __proto__ of any objects created when invoked as a constructor.

var f = new Foo();

So now f is an object with the Foo.prototype in its prototype chain. You can verify this using Object.getPrototypeOf();

Object.getPrototypeOf(f) === Foo.prototype; // true

What Object.create gives you is the ability to set up the same prototype chain, but without using a constructor function. So this would be equivalent.

var f2 = Object.create(Foo.prototype);

Now we have an object that is set up in the same manner as the original f object.

Object.getPrototypeOf(f2) === Foo.prototype;            // true
Object.getPrototypeOf(f2) === Object.getPrototypeOf(f); // true

So it's just a different way of doing what is ultimately the same thing. The relationship between an object and its prototype chain is an internal relationship. The non-standard __proto__ just exposes that relationship.

Upvotes: 5

Matt Ball
Matt Ball

Reputation: 359836

An instance's __proto__ property should be the same as the constructor's prototype property.

When an object is created, its __proto__ property is set to reference the same object as its internal [[Prototype]] (i.e. its constructor's prototype object). Assigning a new value to __proto__ also changes the value of the internal [[Prototype]] property, except where the object is non–extensible.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/proto#Description

Upvotes: 0

Related Questions