0

所以我有这个看起来像这样的 javascript/Backbone 脚本:

var Model = Backbone.Model.extend({});

var View = Backbone.View.extend({

 initialize: function() {
    _.bindAll(this); //bind this
   this.doProcessing();
 },

 doProcessing: function() {

  $('.someElement').each(function() {
      Model myModel = new Model;
      myModel.fetch({                          //issue ajax
         success: function(model, response){   //after successful ajax
            console.log(this)                  // <-- outputs Window!!
       });     

   }); //end each

  } //end processing

});

new View;

让我无法理解的是如何this绑定到窗口。我很清楚我的关闭,但不应该this参考model?

这就是我的理解 - 成功回调以某种方式绑定到 Window 对象。因此,当它被调用时,上下文就是窗口对象的上下文。但在我看来,这有点出乎意料。骨干为什么这样做的任何原因(或者我误解了什么?)。

通过 的参数设置myModel的属性有点奇怪。当它应该允许一个简单的调用时,调用它似乎很复杂modelsuccessmodel.set({...})this.set({...})

在这种情况下我的理解this正确吗?任何解决方法?或者这更像是 XHR 绑定到成功回调的方式?

来自 Backbone 的源代码(Model.fetch):

fetch: function(options) {
      options = options ? _.clone(options) : {}; //cloning options - does this variable get bound to global?
      var model = this;
      var success = options.success;            //or is it this?
      options.success = function(resp, status, xhr) {
        if (!model.set(model.parse(resp, xhr), options)) return false;
        if (success) success(model, resp);
      };
      options.error = Backbone.wrapError(options.error, model, options);
      return (this.sync || Backbone.sync).call(this, 'read', this, options);
    },
4

4 回答 4

1

“成功回调以某种方式绑定到窗口对象”

不,JavaScript 中的函数不是“绑定”的。this仅在调用函数时指定什么。让我们看看它是如何调用的

success(model, resp)

所以函数是直接调用的,不是通过方法调用语法( someObj.someMethod(...)),也不是通过.call()or .apply()。所以在这种情况下,this设置为全局对象,在这种情况下是窗口。

于 2012-08-05T07:48:57.103 回答
0

默认情况下会发生这种情况,因为 .call() 或 .apply() 没有给出任何特定的上下文,它回退到window用作this对象

于 2012-08-04T04:58:24.247 回答
0

一种解决方法是尝试这样的事情

myModel.fetch({                          
     success: _.bind(function(model, response){   
        console.log(this);                  
   },this);
});     
于 2012-08-04T04:12:30.873 回答
0

块的上下文或引用的内容在 javascriptthis中非常不稳定。

我认为上下文的变化是在块中完成的$('.someElement').each(function() { ... });,与工作方式无关Model.fetch()

尝试添加更多日志,例如:

doProcessing: function() {
  console.log( "out of the block", this );

  $('.someElement').each(function() {
    console.log( "begining of block", this );

    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", this );                 
      }     
    });
  };

  console.log( "end of block", this );
}

进入eachthis应该是实际的 DOM 元素进入循环。

为了解决这种this意义的变化,我习惯使用一种解决方法,并且我习惯于看到周围是引用this外的另一个变量(什么时候是你期望的)并将这个新的引用用于堵塞:this

doProcessing: function() {
  console.log( "out of the block", this );

  var _self = this;

  $('.someElement').each(function() {
    console.log( "begining of block", _self );

    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", _self );
      }     
    });
  };

  console.log( "end of block", this );
}

更新

如果您想要引用您最近创建的模型,只需使用您创建的外部引用,如下所示:

doProcessing: function() {
  $('.someElement').each(function() {
    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", myModel );                 
      }     
    });
  };
}

或者只是使用 Backbone 发送到成功回调的引用:

doProcessing: function() {
  $('.someElement').each(function() {
    Model myModel = new Model;
    myModel.fetch({                          
      success: function(model, response){ 
        console.log( "into the fetch", model );                 
      }     
    });
  };
}
于 2012-08-04T09:57:47.667 回答