$.proxy、bind、call、apply的区别

9

旧方式:

var self = this;    
setTimeout(function(){
  console.log(self);
}, 5000);

使用jQuery:
setTimeout($.proxy(function(){
  console.log(this);
}, this), 5000);

使用bind:

setTimeout((function(){
  console.log(this);
}).bind(this), 5000);

使用调用:

setTimeout((function(){
  console.log(this);
}).call(this), 5000);

似乎 apply 也可以工作:

setTimeout((function(){
  console.log(this);
}).apply(this), 5000);

http://jsfiddle.net/SYajz/1/

我想知道这些方法之间是否有一些不那么明显的区别。

你的最后两个示例不起作用 - 它们立即调用回调函数。 - Alnitak
2个回答

9

好的,这里涉及到三种调用函数的方式。它们都是解决上下文问题的方式,即this关键字的值会根据函数的调用方式而有所不同。

别名

var self = this;    
setTimeout(function(){
  console.log(self);
}, 5000);

这是一种非常简单的方法。它只是设置一个新变量,该变量不会在函数内被覆盖。该值被封闭,因此当超时后调用该函数时,self将是您预期的值。

绑定

setTimeout($.proxy(function(){
  console.log(this);
}, this), 5000);

setTimeout((function(){
  console.log(this);
}).bind(this), 5000);

这两个函数的结果完全相同。这是因为$.proxybind执行的功能完全一致。然而,bind是一种新的语法,在某些旧版本浏览器中不受支持。
这种方法通过永久地将上下文“绑定”到一个函数上来实现。这意味着,无论如何调用函数,this的值始终为bind的第一个参数的值。

call/apply

setTimeout((function(){
  console.log(this);
}).call(this), 5000);

setTimeout((function(){
  console.log(this);
}).apply(this), 5000);

这两个函数本质上是相同的,它们唯一的区别在于向函数发送的其他参数。 callapply 之间的唯一差异就是 call 接受列表(例如 fn.call(context, param1, param2)),而 apply 接受数组(fn.apply(context, [param1, param2]))。

这两个函数的作用都是使用特定的上下文来调用函数。

但是,这两个函数都无法实现您想要的效果。它们都立即使用特定的上下文调用函数,而不是等待5秒钟再调用。这是因为 callapply 的工作原理与 () 相同:代码会立即执行。

结论

哪种方法更合适将取决于您的任务。对于简单的操作,重命名可能很好地完成工作。但值得记住的是,这会引入另一个变量,并且无法在调用时设置上下文。其他方法在不同情况下也有其优势,特别是在编写库时用户提供回调函数的情况下。


4
使用$.proxy.bind(),您可以创建一个新函数,其中this值绑定到您提供的值。因此,这是传递给setTimeout()的函数。
使用.call().apply()将立即调用该函数,因此它不会等待计时器。
要使它们与计时器一起工作,您需要返回一个函数,该函数关闭引用所提供的this值的变量,并在给定引用的this上调用console.log()
setTimeout((function(){
  var that = this;
  return function() {
      console.log(that);
  }
}).call(this), 5000);

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