tinybike
tinybike

Reputation: 562

How to make "this" keyword refer to current instance, if used from a nested object's method?

In JavaScript, if I attach a function to an object's prototype, within that function, this refers to the current instance of the object. For example:

function RageFest(inquiry) {
    this.inquiry = inquiry;
}

RageFest.prototype.myFunction0 = function () {
    console.log(this.inquiry);
};

new RageFest("you mad, bro?").myFunction0(); // prints "you mad, bro?"

Running this in Node prints you mad, bro? to the terminal, as expected.

Now, here's where I run into trouble: suppose I want to introduce a second level of organization (maybe because RageFest has lots of methods attached to it, and I want to organize them).

RageFest.prototype.myObject = {
    myFunction1: function () { console.log(this.inquiry); },
    myFunction2: function () { console.log(this.inquiry); }.bind(this),
    myFunction3: function () { console.log(this.inquiry); }.bind(RageFest)
};

var ragefest = new RageFest("you mad, bro?");

ragefest.myObject.myFunction1(); // undefined
ragefest.myObject.myFunction2(); // undefined
ragefest.myObject.myFunction3(); // undefined

None of these work! If I make myObject's three functions log this (rather than this.inquiry), it shows that:

However, binding the instance (rather than the constructor) works:

RageFest.prototype.myObject.myFunction4 = function () {
    console.log(this.inquiry);
}.bind(ragefest);

ragefest.myObject.myFunction4(); // prints "you mad, bro?"

This prints out you mad, bro?, as desired, but it feels like a terrible hack. It also requires me to create an instance of RageFest beforehand, which is annoying.

So, my question is, is there a way of achieving the effect I want -- functions inside a nested object that have access to the current instance using the this keyword -- without resorting to this hackery?

Upvotes: 2

Views: 1214

Answers (1)

abs
abs

Reputation: 801

Instead of creating nested object creating getter will be helpful, which will be called in constructor function and assigned to an object property.

function RageFest(inquiry) {
    this.inquiry = inquiry;
    this.myObject = this.getMyObject();
}

RageFest.prototype.myFunction0 = function () {
    console.log(this.inquiry);
};

RageFest.prototype.getMyObject = function(){
    var that = this;
    return {
      myFunction1: function () { console.log(that.inquiry); },
      myFunction2: function () { console.log(that.inquiry); } 
    }
};

var ragefest = new RageFest("you mad, bro?");
ragefest.myObject.myFunction1();
ragefest.myObject.myFunction2();

Upvotes: 3

Related Questions