"self = this"和apply或bind有什么区别?(Backbone)

3

在我的Backbone代码中,我经常遇到这样的情况,即将闭包传递给某些函数,并且失去了“this”的上下文。

一段时间以来,我的解决方案一直是做我看到其他人做的事情:

var self = this;

this.deferred.done(function () {
    self.render();
});

实际上我改用了_this = this,但这并不重要。虽然它可以工作,但感觉很丑陋,而且有时需要经常这样做。因此,我正在尝试找到更好的方法来解决这个问题。我发现我可以这样做:

this.deferred.done(function () {
    this.render();
}.apply(this));

我认为我也可以使用Underscore来完成这个任务:

this.deferred.done(_.bind(function () {
    self.render();
}, this));
apply方法看起来最简洁,但我觉得它有副作用(我还不知道是什么)。

编辑:

看一下这个JSbin,我在里面使用了类似于我提到的apply的方法: http://jsbin.com/qobumu/edit?js,console

它可以工作,但同时也会抛出一个错误。如果我将apply更改为bind,它就可以正常工作而且不会抛出错误。


4
.apply() 几乎肯定不是你想要的;我认为你在考虑 Function.prototype.bind() - Pointy
3
this.deferred.done(this.render.bind(this)) 可以在不输入单词 "function" 或复制的情况下正常工作。 - dandavis
2个回答

5
  • Function.bind 是一个原生方法,除非你要编写古老的浏览器代码,否则不需要使用 underscore。就像 @dandavis 所说:this.deferred.done(this.render.bind(this)) (但请注意,bind 还可以绑定函数参数,而不仅仅是 this

  • 如果你正在编写最新版本的浏览器或者 node.js 4,你可以使用箭头函数,它会在函数定义时将 this 与当前作用域中的对象进行词法绑定,因此你可以这样写: this.deferred.done(() => { this.render() });


这非常有趣。展望未来的前景很好,但我需要比箭头函数更好的浏览器支持。Bind似乎像apply一样工作,但我现在注意到apply会抛出一个错误(我将在我的原始问题中添加更多信息)。 - Kenmore
是的,因为apply会立即执行函数,正如Alex在他的答案中解释的那样。对于回调函数没有用处。 - Touffy

4

它们做不同的事情。

// returns a function with `this` set to what you want.
_.bind(fn, this);
// or
fn.bind(this);

// EXECUTES the function with `this` set to what you want.
fn.apply(this);

在你的情况下,这根本不是回调函数。当你使用 apply 时,你实际上是在执行函数,而不是分配回调。

这就是为什么要使用 bind。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接