我有一个将函数绑定到单击的事件。单击会在同一视图中调用另一个函数。不幸的是,范围不是正确的范围。当我尝试执行此.otherFunction()时,分配给click的函数与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());
},
这些都属于同一观点。
编辑: 嗯,现在问题是我收到这个错误: 未捕获的TypeError:Object [object DOMWindow]没有方法'renderLeaveGoal'。这似乎是我保存了错误的范围吗?
答案 0 :(得分:5)
标准技术是做类似
的事情var self = this;
然后你可以做
self.otherFunction();
取代
this.otherFunction();
答案 1 :(得分:2)
deltanovember的回答是正确的,但他没有解释为什么这是正确的,我觉得这很重要:
Javascript中的范围很混乱。我发现跟踪它的最简单方法是在执行某些事情时考虑。如果一段代码立即执行,它可能与“this”在同一范围内运行。如果稍后要调用一个函数,它可能在一个完全不同的范围内运行,它有自己的“this”概念。
在您的示例中,您提供的匿名函数作为成功回调将在稍后运行,并且它不会限定为与定义所述回调时运行的代码相同的“this”。这就是您收到错误的原因:renderLeaveGoal是在定义回调的范围内定义的,而不是回调执行的范围。
现在,为了使这更加混乱,定义回调时定义的变量 将在该回调范围内可用。这就是为什么deltanovember的答案有效。通过在定义成功回调时伪装变量中的“this”,回调仍然可以在以后运行时访问它,尽管范围完全不同。
我希望这是有道理的。评论如果没有,我会再试一次:))
答案 2 :(得分:2)
您还可以使用Underscore的bindAll功能,如下所示:
initialize: function() {
_.bindAll(this);
}
在幕后,Underscore将使用代理版本替换对象中的所有函数调用,这些代理版本将“this”设置为与原始对象相同的“this”。当然,如果你的一个方法里面有自己的匿名回调函数,那么你需要完成整个“self = this”舞蹈; bindAll仅修复对象上“外部”方法的上下文。
我已经养成了使用_.bindAll作为我的每个View的initialize()方法的第一行的习惯。
答案 3 :(得分:1)
该函数附加到视图,因此您需要从View对象中调用它。
success: this.renderLeaveGoal
在这种情况下,您不需要匿名函数,因为视图函数会自动绑定到视图的上下文。