Larsi
Larsi

Reputation: 4774

Understanding javascript this scoping - with a simple Backbone example

Take a look at this jsFiddle

Code also listed below:

window.MyView = Backbone.View.extend({

ticks: 0,
initialize: function() {
    //window.setInterval(this.onTimerTick, 1000); // arghhh.. can't understand the 'this' scoping       
    window.setInterval(this.onTimerTick2, 1000);  // Works great with globals       
},

render: function() {
    this.$el.text(this.ticks);            
},

onTimerTick: function() {  // Trouble with this
    this.ticks++;
    this.render();
},

onTimerTick2: function() {  // Using globals
    window.ticks2++;
    $('#count').text(window.ticks2);
}
});

window.My = new MyView({ el: $("#count") });
window.ticks2 = 0;

Looking at the code, you see I would like to use the onTimerTick function, but becouse I can't figure out how to get from the window-this to the My-this, I must use the approach seen in onTimerTick2. (usually I get around with a that=this, but in this case it is not enough)

Thanks for any attemt to make me understand this(!)

Thanks

Larsi

Upvotes: 2

Views: 689

Answers (3)

S.C.
S.C.

Reputation: 2874

You can also rely to _.bindAll utility method, to keep code cleaner and reusable.

initialize: function() {
    _.bindAll(this, 'myFunction')
    setInterval(this.myFunction, 1000)
},

myFunc: function() {
    console.log(this)
}

Upvotes: 0

ori
ori

Reputation: 7847

It looks like backbone uses the bind function from underscore, so:

 window.setInterval(_.bind(this.onTimerTick2, this), 1000); 

Upvotes: 0

ThiefMaster
ThiefMaster

Reputation: 318488

When passing this.onTimerTick2 to setTimeout, the function will be called with this being bound to the global object, not your object.

If underscore.js is available (according to @ori it is), you can use _.bind() to lock this to the correct object when called:

window.setInterval(_.bind(this.onTimerTick, this), 1000);

Here are some solutions that do not depend on a library:

// Works in all browsers
var self = this;
window.setInterval(function() {
    self.onTimerTick();
}, 1000);

With a modern JS engine you can also use Function.bind() to keep the correct this:

// Requires a modern JS engine
window.setInterval(this.onTimerTick.bind(this), 1000);

Upvotes: 2

Related Questions