Nilzone-
Nilzone-

Reputation: 2786

__proto__ vs. prototype inheritance in javascript

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:

enter image description here

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

Answers (1)

zhirzh
zhirzh

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:

  • Elipse = function
  • Rectangle = object
  • Arrow = property
    • p = .prototype
    • c = .constructor
    • P = .__proto__ or [[Prototype]]
  • All anonymous items are empty shapes and all named items contain the name

1) Create a function 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();
}

enter image description here


2) Replace a function's prototype with another object

We 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;
    }
};

enter image description here


3) Add a property to an object or a function

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(){};

enter image description here


4) Replace a function's prototype with another object

Just 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;

enter image description here


Let's clear up the drawings a bit.

enter image description here


5) instantiation

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.

enter image description here

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

Conclusion

Indeed what you originally thought is correct

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?

To gain command over these core concepts of JS, I highly recommend reading http://www.javascripttutorial.net/javascript-prototype/

Upvotes: 2

Related Questions