3

我有一个将函数绑定到点击的事件。单击在同一视图中调用另一个函数。不幸的是,范围不是正确的范围。当我尝试执行 this.otherFunction() 时,分配给单击的函数与 this.otherFunction() 不在同一范围内。有没有办法在 otherFunction() 的范围内传递?

initialize: function() {
  this.render();

  if (joinedGoalList.get(this.model.id) != null) {
    this.renderLeaveGoal();
  } else {
    this.renderJoinGoal();
  }
},

events: {
  "keypress #goal-update": "createOnEnter",
  "click #join-goal": "joinGoal",
  "click #leave-goal": "leaveGoal",
},

joinGoal: function() {
  matches = joinedGoalList.where({id: this.model.get("id")});
  if (matches.length == 0) {
    joinedGoalList.create({goal_id: this.model.get("id")}, {wait: true, success: function() {
      var self = this;
      self.renderLeaveGoal();
    }, error: function() {
      console.log("error");
    }});
  }
},

renderLeaveGoal: function() {
  console.log("render leave goal");
  var template = _.template($("#leave-goal-template").html());
  console.log(template);
  $("#toggle-goal-join").html(template());
},

这些都是同一个观点。

编辑:嗯,现在的问题是我收到了这个错误:未捕获的类型错误:对象 [object DOMWindow] 没有方法“renderLeaveGoal”。这似乎是我保存了错误的范围吗?

4

4 回答 4

5

标准技术是做类似的事情

var self = this;

然后你可以做

self.otherFunction();

代替

this.otherFunction();
于 2012-04-21T02:15:14.420 回答
2

deltanovember 的回答是正确的,但他没有解释为什么它是正确的,我觉得这很重要:

范围在 Javascript 中很混乱。我发现跟踪它的最简单方法是考虑什么时候会执行。如果一个代码块立即执行,它可能与“this”在同一范围内运行。如果稍后要调用一个函数,它可能运行在一个完全不同的范围内,具有自己的“this”概念。

在您的示例中,您作为成功回调提供的匿名函数将在稍后运行,并且它不会被限定为与定义所述回调时正在运行的代码相同的“this”。这就是您收到错误的原因:renderLeaveGoal 是在定义回调的范围内定义的,而不是在将执行回调的范围内。

现在,为了使这更加混乱,定义回调时定义的变量在该回调的范围内可用。这就是 deltanovember 的答案有效的原因。通过在定义成功回调时将“this”伪装在变量中,回调在稍后运行时仍然可以访问它,尽管范围完全不同。

我希望这是有道理的。如果没有,请评论,我会再试一次:)

于 2012-04-21T08:05:46.840 回答
2

你也可以像这样使用 Underscore 的bindAll函数:

initialize: function() {
    _.bindAll(this);
}

在幕后,Underscore 会将对象中的所有函数调用替换为将“this”设置为与原始对象相同的“this”的代理版本。当然,如果您的某个方法内部有自己的匿名回调函数,那么您将需要完成整个“self = this”舞蹈;bindAll 仅修复对象上“外部”方法的上下文。

我已经养成了使用 _.bindAll 作为 View 的每个 initialize() 方法的第一行的习惯。

于 2012-04-21T21:56:06.260 回答
1

该函数附加到视图,因此您需要从视图对象中调用它。

success: this.renderLeaveGoal

在这种情况下,您不需要匿名函数,因为视图函数会自动绑定到视图的上下文。

于 2012-04-21T02:17:38.443 回答