假设我们在一个基于模型的视图中,并且我们想要绑定到模型的更改事件:
this.model.on('change', this.render);
on 调用看到两件事:
- 事件名称,一个简单的字符串。
- 处理程序,一个函数。
on 无法知道this 在this.render 中的含义,它只是看到一个函数; on 甚至不知道上面的调用和这个之间的区别:
this.model.on('change', function() { ... });
如果您的函数需要特定的上下文,那么您有两种选择:
- 使用
_.bind、_.bindAll、Function.bind、$.proxy、CoffeeScripts =>、var _this = this 闭包技巧或任何创建或模拟绑定函数的方法创建绑定函数。
-
告诉它你想要哪个上下文:
this.model.on('change', this.render, this);
无法展开调用堆栈以查看您想要哪个this,因此您必须明确说明。
Backbone 会这样调用回调:
node.callback.apply(node.context || this, ...);
其中node.callback 是回调函数,node.context 是给on 的第三个参数(如果有)。如果你不指定上下文,那么当trigger 被调用时,你会得到this 的任何内容;在上面的示例中,this 最终会成为模型。
所以on 的第三个参数实际上是可选的,但默认值并不是非常有用,也没有办法选择更好的默认值,您需要选择合理上下文的信息在 JavaScript 中根本无法访问.这就是为什么您会在 Backbone 视图中看到如此多的 _.bindAll(this, ...) 样板。
如果你尝试过这样的事情:
model.on = function(event, callback){
model.on_with_three_args.call(this, event, callback, this);
});
那么 this 在这种情况下通常是 model 所以你真的会说:
model.on = function(event, callback){
model.on_with_three_args.call(model, event, callback, model);
});
或
model.on = function(event, callback){
model.on_with_three_args(event, callback, model);
});
而且没有任何意义。 on 中的this 的值与调用on 的代码中的this 的值几乎没有关系。 JavaScript 中的this 不是变量,它是一个关键字,表示当前调用上下文。