How Does _Proto_ Differ from Constructor.Prototype

How does __proto__ differ from constructor.prototype?

I've been trying to wrap my head around this recently and finally came up with this "map" that I think sheds full light over the matter

http://i.stack.imgur.com/KFzI3.png
Sample Image

I know I'm not the first one making this up but it was more interesting figuring it out that finding it :-). Anyway, after that I found e.g. this another diagram that I think says basicly the same:

Javascript object layout

The most surprising thing for me was discovering that Object.__proto__ points to Function.prototype, instead of Object.prototype, but I'm sure there's a good reason for that :-)

I paste the code mentioned in the image here as well for if anyone wants to test it. Note that some properties are added to the objects for making easy to know where we are after some jumps:

Object.O1='';
Object.prototype.Op1='';

Function.F1 = '';
Function.prototype.Fp1 = '';

Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';

mycat = new Cat();
o = {};

// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);

__proto__ VS. prototype in JavaScript

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new:

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

__proto__ and prototype difference

__proto__

You can actually access the internal [[Prototype]] property of an object with __proto__. You can think of [[Prototype]] as the actual parent of the current object, in the inheritance hierarchy.

prototype

This is a special property, when set on a (constructor) function object, used to establish the inheritance chain for instances created from the constructor. For example,

function Foo() {}
Foo.prototype = {a: 1};

Now, when you create a new object of type Foo, the newly created object's internal [[Prototype]] property will refer the Foo.prototype object. You can confirm that like this

console.assert((new Foo()).__proto__ === Foo.prototype);

In your case,

myFunc.prototype = myObj;

you are creating a prototype property on the function object and this will be used only when you are creating new objects with this function (constructor function). You might want to think of it as a template for the new objects. So, when you do myFunc.a, JS engine tries to find a in myFunc and its parents in the prototype chain and it doesn't find it, that is why it returns undefined.

But, when you do

myFunc.__proto__ = myObj;

you are setting the parent of myFunc, in the prototype chain, to myObj. So, when you do myFunc.a, JS engine first tries to find a in myFunc object itself, and it is not there. So, it tries to find it in its immediate parent, which is myObj. That is why it returns 1 in this case.


Note: You can use the following function to understand the prototype chain better

function printPrototypeChain(object) {
while (object !== null) {
console.log(object);
object = Object.getPrototypeOf(object);
}
}

Now, let us print the prototype chain when the object is set as the prototype property of the function object.

function myFunc() {}
myFunc.prototype = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);

The output will be

[Function: myFunc]
[Function: Empty]
{}

None of these objects have a defined, so undefined is returned. But, in this case,

function myFunc() {}
myFunc.__proto__ = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);

the prototype chain becomes like this

[Function: myFunc]
{ a: 1, b: 2 }
{}

and a is found in myFunc's immediate parent. So, corresponding value 1 is returned.

Note: Don't use __proto__ in your actual code, as it is retained in the latest versions of JavaScript specification just for backward compatibility. Read more about it here. Use Object.getPrototypeOf and Object.setPrototypeOf instead.

Trying to understand the difference between prototype and constructor in JavaScript

It is pretty hard to wrap your mind around this concept if you are used to the ease of extending objects in other OOP languages, but I'll do my best to explain the uses of those and what is what. I am going to assume you are familiar with other OOP languages. Correct me if I'm wrong.

All functions have the prototype Function(). They are inheriting all base functionality from Function like toString() and valueOf().

Then there is a constructor. That is what you use to initialize an object with.

p = new Foo();

So in this case we have two things.

  • A function Foo with Function as prototype(Foo)
  • A Function object with Foo() as constructor(p)

(following me yet?)

The Foo() constructor can override some base functionality of the Function constructor or leave it as it is and make good use of it.

If you are familiar with OOP principles, The prototype is the base class, the constructor your current class. In OOP the above would be class Foo extends Function

You can also start inheritance with this entire setup of prototype and constructor making more complex objects as you go whilst sharing functionality.

For example this:

// Make an object initialiser extending Function. In OOP `class Foo extends Function`

function Foo(bar) {
this.baz = bar;
}
Foo.prototype.append = function(what) {
this.baz += " " + what;
};
Foo.prototype.get() {
return this.baz
}

Now lets say we want different ways to get baz out of there. One for console logging and one for putting it on the title bar.
We could make a big thing about our class Foo, but we don't do that, because we need to do wholly different things with the new classes that are made for different implementations. The only thing they need to share are the baz item and the setters and getters.

So we need to extend it to use an OOP term. In OOO this would be the desired end result class Title extends Foo(){}. So lets take a look at how to get there.

function Title(what) {
this.message = what;
}

At this point the Title function looks like this:

  • prototype Function
  • constructor Title

So, to make it extends Foo we need to change the prototype.

Title.prototype = new Foo();
  • prototype Foo
  • constructor Foo

This is done by initializing a new Foo() object against the prototype.
Now its basically a Foo object called Title. That is not what we want because now we can't access the message part in Title.
We can make it properly extend Foo() by resetting the constructor to Title

Title.prototype.constructor = Title;
  • prototype Foo
  • Constructor Title

Now we are faced with one more problem. The constructor of Foo doesn't get initialized so we end up with an undefined this.baz

To resolve that we need to call the parent. In Java you would do that with super(vars), in PHP $parent->__construct($vars).

In Javascript we have to modify the Title class constructor to call the constructor of the parent object.

So the Title class constructor would become

function Title(what) {
Foo.call(this,what);
this.message = what;
}

By using the Function object property Foo inherited we can initialize the Foo object in the Title object.

And now you have a properly inherited object.

So instead of using a keyword like extend like other OOP languages it uses prototype and constructor.

Constructor property : __proto__.constructor vs prototype.constructor

a.__proto__ is the Function prototype (namely, Function.prototype). It is the object from which all functions inherit function-specific methods like call, apply, bind, etc. It is true that a.__proto__.bind == a.bind.

a.__proto__.constructor is the Function constructor, i.e., the function Function. The Function prototype has a reference to its associated constructor via the constructor property, as is always the default relationship between prototype object and constructor. (More on this "default relationship" in the next two paragraphs.)

Quite different is a.prototype -- in JavaScript, any function can be a constructor, i.e., it may be called with new. Whenever a function is called with new, it creates a new object whose __proto__ is the function's prototype and points to the newly-created object via this. So inside a call to new a() it is true that this.__proto__ equals a.prototype. This prototype object is automatically created and stored in a.prototype at the moment the function a is defined.

a.prototype.constructor is equal to a, because the JavaScript internal routine that creates prototype objects for newly-defined functions (as specified in the previous paragraph) always gives that new prototype a constructor property that refers to the newly-defined function. To get really into the weeds, the relevant ECMAScript routine is 19.2.1.1.1, CreateDynamicFunction, which notes, "A prototype property is automatically created for every function created using CreateDynamicFunction, to provide for the possibility that the function will be used as a constructor."

a does not have its own constructor property, but it automatically inherits a.__proto__.constructor accessible as a.constructor, just as it inherits any other properties on its prototype parent (just like a.bind is really a.__proto__.bind).

Finally, a.__proto__.constructor !== Object.prototype.constructor because Object.prototype is not a function object's prototypal parent, but instead Function.prototype is. It is instead true that a.__proto__.constructor === Function.prototype.constructor (and, more succinctly, a.__proto__ == Function.prototype and a.__proto__.constructor == Function).

__proto__ VS. prototype in JavaScript

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc. prototype is the object that is used to build __proto__ when you create an object with new:

( new Foo ).__proto__ === Foo.prototype
( new Foo ).prototype === undefined

[[Prototype]] vs prototype: ..what is the difference? (MyCons.__proto__ === MyCons.prototype) equals FALSE

Think of it like this. MyConstructor is a function object, so it was created by Function; therefore its [[Prototype]] (or __proto__) is identical to Function.prototype.

In the same way, var myObj = new MyConstructor() creates an object myObj with a [[Prototype]] identical to MyConstructor.prototype.

To put it another way, functions have a prototype property, and when you invoke functions with new, they will construct an object having a [[Prototype]] identical to the constructor function's prototype property... however a function's prototype property is not the same thing as its [[Prototype]] (or __proto__) property, because a function follows the same rules as other objects and gets its internal [[Prototype]] property from the function that constructed it (which is always Function, incidentally).


To explain further, [[Prototype]] and prototype have entirely different purposes. [[Prototype]] is used when resolving an object's properties. If an object doesn't have a property, its [[Prototype]] is checked, and then that object's [[Prototype]], and so on, until either a property is found or you hit the end of the prototype chain.

In contrast, prototype is the mechanism by which you assign [[Prototype]] properties to objects, since you can't access them directly other than with the non-standard __proto__ property.

Since functions are objects, they have both a [[Prototype]] internal property, used to resolve properties as with normal objects, and a prototype property, which is assigned as the [[Prototype]] of new objects constructed by the function.



Related Topics



Leave a reply



Submit