在Backbone.Model中使用_.bindAll

时间:2012-09-05 11:54:27

标签: backbone.js this underscore.js

我仍然对如何使用_.bindAll()感到困惑。我了解有时会引用另一个对象,因此我们需要使用_.bindAll()来纠正它。

例如,我在这里无法使用this.setLevelTimer(false),因为this指向setTimeout,所以我在哪里放_.bindAll()

如果this未正确指向多个实例,该怎么办?我使用多个_.bindAll() s?

var model = Backbone.Model.extend({
    initialize: function(){

    }
    ...
    setLevelTimer : function (){

        if (delta < 0){
             this.gameOver();
        } else {
            gameState.timer = setTimeout(function(){
                return this.setLevelTimer(false);  //"this" does not work
            }, 30);
        }
    }
    ...
});

2 个答案:

答案 0 :(得分:1)

_.bindAll将此对象绑定为函数范围的初始化对象。

如果在函数内部嵌套了作用域,则此对象可能不同。

例如

setLevelTimer: function(){
  // this should equal to the initialized model
  $("a").click(function(){
    // the this variable here is the clicked DOM object - not the initialized model
  });
}

这个问题的一个常见解决方案是在函数的第一行设置一个变量,然后你也可以在嵌套作用域内使用它(只要它当然没有重新定义),例如:

setLevelTimer: function(){
  // this should equal to the initialized model
  var that = this;
  $("a").click(function(){
    // the that variable here is the initialized model
  });
}

答案 1 :(得分:0)

_.bindAll将给定对象的函数属性“this绑定到给定对象。 Docssource

您正在做的是假设this在您提供给setTimeout的匿名函数中正确设置,但是怎么可能,因为匿名函数不是模型的函数属性

这就是为什么你必须提供具有正确this的匿名函数,至少有以下两种方式:

var self = this; // store correct this into a variable
gameState.timer = setTimeout(function(){
     return self.setLevelTimer(false); 
}, 30);

// use bind to bind your anonymous functio to the right this
gameState.timer = setTimeout(_.bind(function(){ 
   return this.setLevelTimer(false); 
}, this), 30);

希望这会有所帮助(并为您解决问题)!

P.S。

至于回答你原来的问题。这个问题不是_.bindAll的错,您应该在_.bindAll(this)函数中使用initialize来保持Backbone对象的函数绑定到正确的this,但是作为bindAll不会不会影响你动态创建的匿名函数,你需要使用其他措施(我在上面描述的一些措施)来保持它们与你想要的this绑定。