Arek S
Arek S

Reputation: 4699

javascript object variable scope

I have a MessageHelper object which has a idx var. Now I want to access and modify it from index method. I thought that 'this' would do but I'm getting NaN. Any clue?

var MessageHelper = {
        idx: 8,
        formatDate: function(){
            return function(text, render) {
                // // parse date
                var date = $.trim(render(text));
                var mom = moment(date);
                return mom.format("D/M/YY");
            }
        },
        formatDateTime: function(){
            [...]
        },      
        getImportance: function(){
            [...]
        },
        index: function(){
            return function(text, render) {
                this.idx++;
                return this.idx;
            }
        }
    }   

Upvotes: 0

Views: 54

Answers (2)

nicosantangelo
nicosantangelo

Reputation: 13716

The scope (this) inside the function returned by index is the function itself. Outside index, this refers to MessageHelper.

So basically you have to do something like:

var MessageHelper = {
        idx: 8,
        index: function(){
            var self = this; // MessageHelper
            return function(text, render) {
                self.idx++;
                return self.idx;
            }
        }
    }   

You could also use bind but it's not supported in older browsers.

Tip: if you're not defining a constructor, the convention is to name objects with lowercase. In your case messageHelper.

Upvotes: 1

Tibos
Tibos

Reputation: 27823

The value of this inside a function depends on how that function is called. If you want a function to always be called with a certain value as this, the simplest way is to use Function.prototype.bind:

    index: function(){
        return function(text, render) {
            this.idx++;
            return this.idx;
        }.bind(this); // <--- HERE
    }

In this example i relied on the fact that the outer function will be called like this:

MessageHelper.index()

So inside it, this will actually be MessageHelper. Thus, MessageHelper will be this inside the function returned by index as well.

If you plan to do stuff like pass the index function as parameter somewhere, it won't be called as expected and the whole thing will fail. In this case you should bind to MessageHelper:

var MessageHelper = {
  index : function(){}.bind(MessageHelper);
}

var myIndex = MessageHelper.index;
myIndex(); // this will return the correct function, bound to MessageHelper

Upvotes: 2

Related Questions