Reputation: 2786
First of all, this question is really similar to several others on this site. I have read them, but still have questions
These two helped, but didn't get me all the way:
I have this basic setup of a javascript framework/library:
(function(global){
var TMath = function() {
return new TMath.init();
}
TMath.prototype = {
add: function(a, b) {
return a+b;
}
};
TMath.init = function(){};
TMath.init.prototype = TMath.prototype;
global.TMath = global.$$ = TMath;
})(window);
When I run it like so:
var test = $$()
console.log(test);
I see the following in my console:
What I don't understand is:
If I console.log
out test.__proto__
, I get Object{}
.
Shouldn't I get TMath.Init.prototype
, since that's the function constructor
my test
instance was created with?
Here is an example where this does happen:
function Person(name){
this.dob = dob
};
var person = new Person("name");
console.log(person.__proto__);
This outputs Person{}
, and not Object{}
Upvotes: 3
Views: 845
Reputation: 3449
Let's walk through your code piece by piece and see what we end up with.
In the following image(s), this is the nomenclature:
.prototype
.constructor
.__proto__
or [[Prototype]]
TMath
When a function is created, JS engine also creates an anonymous object and binds the two using .prototype
and .constructor
properties as follows:
function foo(){}
/* performed by JS engine */
// foo.prototype = {};
// foo.prototype.constructor = foo;
var TMath = function() {
return new TMath.init();
}
prototype
with another objectWe are re-assigning the link TMath.prototype
, so that it now points to the new object.
This new object also has an anonymous function in it, referenced by .add()
.
And the said function comes with its own default .prototype
object.
TMath.prototype = {
add: function(a, b) {
return a+b;
}
};
This one is simple. Just add a new link to the object/function to which the new property is added.
In our case, the link is .init()
and the property is an anonymous function.
TMath.init = function(){};
prototype
with another objectJust like step 2, we re-assign the link TMath.prototype
.
But rather than creating a new object, we point it to an existing object.
TMath.init.prototype = TMath.prototype;
Still with me?
Good! Becaue this is where the magic happens.
When you do var test = $$()
, you are actually doing var test = TMath()
, which is just var test = new TMath.init()
We can even say that this is the exact same as
var test = new <function referenced by TMath.init>()
.
When using new
while invoking the function, the following rule applies:
If
new
is used in assignment, the returned object is provided with the property.__proto__
(or[[Prototype]]
), which is a reference to the object referenced by
constructor-function's.prototype
Therefore, the created object (in this case test
) has a property __proto__
that points to the TMath.init.prototype
.
And you can confirm all this by doing the following:
console.log(test.__proto__ === TMath.init.prototype) // true
console.log(test.__proto__ === TMath.prototype) // true
Indeed what you originally thought is correct
If I
console.log
outtest.\_\_proto\_\_
, I getObject{}
.Shouldn't I get
TMath.Init.prototype
, since that's the function constructor mytest
instance was created with?
To gain command over these core concepts of JS, I highly recommend reading http://www.javascripttutorial.net/javascript-prototype/
Upvotes: 2