__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
Difference between __proto__ and [[ Prototype ]] in javascript
Each object's prototype is saved in the internal slot named as [[prototype]]
and __proto__
is just a getter/setter, defined in the Object.prototype
object, to get the value of the [[prototype]]
internal slot of any object.
Example:
const arr = [];
Each instance of an array gets Array.prototype
as its prototype. So, in the above declaration of arr
, [[prototype]]
internal slot contains a reference to Array.prototype
and in the following expression:
arr.__proto__ === Array.prototype // true
arr.__proto__
gets the Array.prototype
object from the internal [[prototype]]
slot.
As mentioned above, __proto__
is just a getter/setter that gets the value of [[prototype]]
internal slot and is only there for compatibility reasons. It shouldn't be used in modern javascript code; following two methods should be used to set/get the prototype of any object:
Object.setPrototypeOf()
Object.getPrototypeOf()
There are other internal slots, apart from [[prototype]]
, mentioned in the Ecmascript specification and these internal slots are not accessible by the javascript code we write.
If you need to know more about internal slots, read:
What is an "internal slot" of an object in JavaScript?
__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.
[[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.
__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
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
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);
Function object __proto__ and prototype property
You already know that Object.getPrototypeOf(Animal)
(or Animal.__proto__
) is the Function.prototype
object. So let's drop that Animal
thing and just repeat your equations with Function.prototype
:
Function.prototype.constructor.__proto__ == Function.prototype.constructor.prototype // true
Function.prototype.constructor.__proto__ == Function.prototype // true
Now, the .constructor
property of Function.prototype
(like for all well-defined prototype objects) points to its respective constructor, the Function
constructor function. So we've got
Function.__proto__ == Function.prototype // true
Function.__proto__ == Function.prototype // true
Now, given that Function
is a function, it only makes sense that it inherits from Function.prototype
like all other functions do.
This is what your testing confirms, as you basically did
Function.__proto__.test = 28;
Function.__proto__.test // 28
Function.prototype.test // 28
And yes, Function.test
and Animal.test
would yield 28
as well now.
Object.getPrototypeOf() vs .prototype
TL;DR
function MyConstructor() {}
var obj = new MyConstructor()
Object.getPrototypeOf(obj) === obj.prototype // false
Object.getPrototypeOf(obj) === MyConstructor.prototype // true
MyConstructor.prototype // MyConstructor {}
obj.prototype // undefined
MyConstructor.prototype.constructor === MyConstructor // true
Object.getPrototypeOf(MyConstructor) === Function.prototype // true
The confusing part about prototypes in javascript is that there are 2 different things that sound very similar.
When you create a new object, if the function or object used to create the new object has a .prototype method, then the object referenced by .prototype
will become the new object's prototype newObj.__proto__
.
Sounds complicated... let's break it down further.
A. The .prototype property
Example - Using a function as a constructor
When you use the new
keyword on a function (i.e. you use the function as a constructor) then the function's .prototype becomes the new obj.__proto__
.
Lets first make a function and checkout this .prototype property
function MyConstructor(){
}
console.log(MyConstructor.prototype) // {}
Wait up... MyConstructor.prototype // {}
- did something magically happen? Where did this empty object {}
come from?
2 things here:
Javascript automatically creates a .prototype object whenever you declare a function - automagically.
This object is not empty. It actually has a property that points back to the function that created the object (the object's 'constructor'). Let's check it out:
console.log(MyConstructor.prototype.constructor); // [Function: MyConstructor]
MyConstructor.prototype.constructor === MyConstructor // true
So for functions, the .prototype property and it's associated object are created automatically.
Still confused? Lets add some methods in there to make it easier to see what's going on...
function MyConstructor(){
}
MyConstructor.prototype.func2 = function(){
};
console.log(MyConstructor); // [Function: MyConstructor]
console.log(MyConstructor.prototype); // MyConstructor { func2: [Function] }
MyConstructor.func2(); // TypeError: MyConstructor.func2 is not a function
Clearly we can see from the above code that MyConstructor and MyConstructor.prototype are 2 separate entities.
B. An object's prototype
An object's prototype (not .prototype - see A. above) is what javascript uses to lookup and resolve methods that aren't already in the object (more on this later).
Continuing on from above, when we create an object from a function or object that has a .prototype property, the newly created object will have it's object.__proto__
referencing this .prototype object.
An object's prototype can be accessed by
Object.getPrototypeOf(obj)
or the deprecated
obj.__proto__
Example - Using a function as a constructor
Lets make a new object using the function MyConstructor as a constructor.
function MyConstructor(){
}
var obj = new MyConstructor()
console.log(Object.getPrototypeOf(obj)); // {}
Here are the three relevant things:
- MyConstructor (a function)
- obj (an object that was created from MyConstructor)
obj.__proto__
--> MyConstructor.prototype
So obj.__proto__
is MyConstructor.prototype
. Here is the proof:
MyConstructor.prototype === Object.getPrototypeOf(obj) // true
Lets add a method to MyConstructor
function MyConstructor(){
this.func1 = function(){
console.log("this is func1");
};
}
var obj = new MyConstructor();
obj.func1(); // this is func1
From the above you can see that you can call methods that were declared in the constructor. In fact, if we have a look, our declared method func1 is actually part of obj due to the way javascript creates objects.
console.log(obj); // MyConstructor { func1: [Function] }
We can also add methods that obj can use by adding the methods to the prototype. e.g.
MyConstructor.prototype.func2 = function(){
console.log("this is func2");
};
obj.func2(); // this is func2
MyConstructor and MyConstructor.prototype methods will be available to all objects created using MyConstructor using this setup.
Useful References
Definitive Guide to Object-Oriented JavaScript
Understanding JavaScript: Inheritance and the prototype chain
A Plain English Guide to JavaScript Prototypes
Related Topics
Convert Date to Another Timezone in JavaScript
How to Get Image Size (Height & Width) Using JavaScript
Generate Random String/Characters in JavaScript
Is JavaScript Guaranteed to Be Single-Threaded
Disable/Enable an Input With Jquery
How to Force Js to Do Math Instead of Putting Two Strings Together
Difference Between Null and Undefined in JavaScript
JavaScript Open in a New Window, Not Tab
How to Set Object Property (Of Object Property Of..) Given Its String Name in JavaScript
What Is the !! (Not Not) Operator in JavaScript
How to Add a Delay in a JavaScript Loop
How to Sort an Object Array by Date Property
Is There an "Exists" Function For Jquery
Rails 4: How to Use $(Document).Ready() With Turbo-Links
JavaScript Get Clipboard Data on Paste Event (Cross Browser)