mAu
mAu

Reputation: 2018

Prototypes and object creation

Lately I'm trying to get the technical aspects of the prototype chain. Now I have a few questions about object instantiation.

Consider the following code:

var Foo = function(s) {
  this._bar = s;
};

var fooInst = new Foo('test');

Now when I examine the created object, then:

Foo.prototype === Function.prototype; // true

fooInst.prototype === ?
fooInst.prototype.prototype === Object.prototype; // true

I'm wondering, what fooInst.prototype exactly is. In Chromes inspector it seems to be some kind of Foo with an constructor property. But all sources I read about prototypes state that fooInst.prototype === Foo.prototype should be true.

So my question: how exactly does JS handle the prototype chain. What exactly happens when I call new Foo.

Thanks in advance!

Edit

So I found, that (in Chrome) Object.getPrototypeOf(fooInst) === Foo.prototype; is true, but Object.getPrototypeOf(fooInst) === Object.getPrototypeOf(Foo) is false. Why that?

Upvotes: 3

Views: 554

Answers (3)

user113716
user113716

Reputation: 322452

I'm wondering, what fooInst.prototype exactly is.

It is undefined.

fooInst.prototype === undefined; // true

Only functions have an automatic .prototype property. Objects do not.

If you create an object using a constructor, like:

var fooInst = new Foo('test');

...then fooInst will have an internal reference to Foo.prototype, but there's no standard property to get Foo.prototype from fooInst.


That said, there is a non-standard property that is supported in some JavaScript environments for referencing the prototype object.

fooInst.__proto__ === Foo.prototype; // true (if __proto__ supported)

Also, there is a method provided by ECMAScript 5 that can be used.

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

That internal reference from an object to its prototype object can be just the first in a chain of such references.

The prototype object likely has its own prototype object that is referenced. (In basic cases, this will be Object.prototype, or with longer chains, Object.prototype may be further down the chain.)

Object.prototype itself references null as its prototype. This ends the chain.

You should note that the internal reference from an object to its prototype object does not change if you change the .prototype object of the constructor function. It is a reference that exists for the life of the object.

var Foo = function(s) {
  this._bar = s;
};

var fooInst = new Foo('test');

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

// Change the prototype object of Foo
Foo.prototype = { some:'object' };

Object.getPrototypeOf( fooInst ) === Foo.prototype;  // false

Upvotes: 6

Christian C. Salvadó
Christian C. Salvadó

Reputation: 827218

Your first assumption:

Foo.prototype === Function.prototype;

Is not right, I think you are mixing up the concept of the [[Prototype]] internal property that all objects have, and makes the "link" of the prototype chain, and the prototype property that function objects have.

The above comparison will produce false because the value of the Foo.prototype property is a new object, created at the time you created the Foo function.

This object is initialized whenever you create a function object, it inherits from Object.prototype and it has a property, named constructor that points back to the function (Foo.prototype.constructor === Foo), and it's used when you call your function as a constructor.

Now, if we talk about the [[Prototype]] internal property, you are right, the [[Prototype]] of your Foo function is Function.prototype in other words, Foo inherits from Function.prototype, e.g.:

Object.getPrototypeOf(Foo) === Function.prototype; // true
Foo instanceof Function; // true
Foo.__proto__ === Function.prototype; // true

About fooInst this object was created in a new expression, when you used your Foo function as a constructor, this new object is produced, and it inherits from Foo.prototype, (its internal [[Prototype]] property points to Foo.prototype).

It doesn't have a prototype property, since this property is only meaningful for function objects.

See also:

Upvotes: 2

Jonny Buchanan
Jonny Buchanan

Reputation: 62793

You might find the explanations and diagrams in JavaScript. The Core useful here.

All objects have a prototype chain. As such, fooInst has a prototype chain, at the head of which is Foo.prototype. When you called new Foo, an Object was created, Foo.prototype was set as its prototype chain and the constructor function was called in the context of the new Object.

Some browsers expose this as a non-standard __proto__ property, such that:

fooInst.__proto__ === Foo.prototype

Upvotes: 1

Related Questions