$.proxy()和bind()有什么区别?

30

2009年,ECMAScript 5添加了内置的bind()函数,它以一个对象作为参数并返回一个相同的函数,其中this将始终引用您传递的对象。(我无法找到任何类似于规范文档链接的东西。)

这与jQuery的$.proxy()函数有什么不同?是否在ECMAScript 5发布之前就已经存在$.proxy()?有没有特别的理由支持$.proxy(function(){}, this)而不是function(){}.bind(this)

5个回答

37

proxy 函数是先出现的,但是你应该更倾向于使用 bind 函数,因为它是标准的写法。它们的调用方式略有不同(因为 bind 函数附加在 Function.prototype 上,而 proxy 函数只是一个函数),但它们的行为是相同的。

这里有一篇很好的文章:jQuery.proxy() usage,最后也给出了这个建议。


9

编辑

请不要关注这篇文章(尽管它是被接受的答案)。 长话短说,这是我的错,因为我对问题的上下文做出了假设,而没有查找API文档,在我意识到自己的愚蠢(在未验证其假设的情况下做出假设)并删除它之前,它被接受为答案。

Matt Whipple的答案是100%正确的,虽然我不同意他的观点,即在JS中真正的代理无用(在某些低级关注点上,它们将非常好),但他的其他陈述是完全客观正确的(除了.bind.proxy的实际日期,因为.bind在规范中出现的年份比它在浏览器中稳定地出现之前要早几年)。

以下是我的耻辱,供大家观看......

随便扔西红柿。
如果你想知道我为什么会以这种方式回答,请阅读下面的评论。


$({}).proxy()func.bind({})之间的区别在于代理是一种松散的连接。 你随时可以分离。

这就是代理的作用。 在您想要做的事情和实际执行它的东西之间的无形界面。

值得一提的是,还有一个$.bind(),它不是代理。也就是说,它完全绑定到this,就像func.bind()一样,而不是实现一种中介系统来随时附加和分离函数的上下文。


3
这两个函数都是高阶函数,返回能确保上下文一致性的函数。在JS中使用其他形式创建“代理”只会浪费资源。jQuery中唯一具有绑定功能的是熟知的$.fn.bind,用于附加事件监听器。 - Matt Whipple
我不确定你所说的“松动连接”是什么意思。你能否解释一下? - Jo Liss
1
@JoLiss 我很乐意。可惜,这个答案是我记录中的黑点之一,并且回答得不好,原因是a)我对jQuery API的位置做了一些假设(基于我读过的源代码,而不是与API文档协商),因为b)我在jQuery的$.bind ()的用途上出现了精神失误,与Function.prototype.bind()相比。我无法删除它,因为它奇妙地被接受为答案,比我意识到我的假设有多愚蠢还要快。也许我现在会尝试编辑它,既然你提醒了我。 - Norguard
@JoLiss 就记录而言,在我写这篇文章的时候,我的头脑正忙于在元素上不可见地管理侦听器注册和撤销的系统中,这些元素隐藏在 $.bind()(以及类似的 jQuery 静态/实例方法)的幕后。那就是我所指的代理,因为它实际上负责充当动态分派的代理,并且是一个更有趣的问题需要解决(因为直到现在,JS 没有一个优雅的解决方案来实现实际代理;多态性很多,但没有代理)。PS:感谢 Broccoli。 - Norguard
“代理在JS中是浪费的”这个说法有点过激了。在某些情况下,它们肯定是有用的。一些代理相关的模式,比如装饰器,在JS中可以通过混入和一级函数更简单地处理,这被推广到了我对问题的看法上。基本上,当代理是你想要的东西时,它们是一个很好的选择,但不应该盲目使用,因为它们是语言X中唯一的选择。 - Matt Whipple
1
ROFLMFAO,这是我在SSO上见过的最搞笑的回答。 - Tilak Madichetti

8

$.proxy 函数首先被提出来。以下是在函数调用时保留特定上下文的简单方法。

var myProxy = (function(context,fn){
  return function(){
      fn.call(context);
  }
})( myContext, myFn );

你可以在jquery推出之前轻松地使用它。
答案很简单: bind 是官方支持的。如果脚本需要运行,就使用支持bind的浏览器。

6

1

这里有一个你可以尝试的测试,用于性能比较。

http://jsperf.com/bind-vs-jquery-proxy/5

现在是2014年10月。 不同浏览器的性能差异非常大。 IE 11原生绑定速度最快。

然而,在我测试的三个浏览器中,原生绑定都比jquery代理更快。 并且由于bind()是标准的,所以如果可能的话建议坚持使用它。


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