.apply和.call有什么区别?

4

我经常在使用jQuery对象和常规js对象时遇到问题; 我正在尝试找出如何在适当时使用.call和.apply的方法。 我一直在测试代码以查看它实际上的作用。

但是,当我在已知具有jQuery的网站上运行下面的代码(其基本上只隐藏页面上的所有div)时,会得到各种结果; 我想知道这是否与jQuery版本相关,还是这段代码仅仅是“有缺陷”的。我要破解为什么.call总是有效,而.apply却不起作用,尽管根据下面的代码应该是相反的。

var myApp = {} // instantiate an empty objct
myApp.hide = function (whatever) {
   that = whatever
   $(that).hide()
}
var Numbers = function (object) {
this.object = object;
}

Numbers.prototype.div = $('div');
var numbers = new Numbers();
numbers.div
myApp.hide.call(numbers, numbers.div)
myApp.hide.apply(numbers, numbers.div)

当我使用.call或.apply火狐调试上述代码时,结果会因网站而异。每个有jQuery的网站都可以使用.call,但对于一些网站,如jQuery.com和Twitter,两者都可以使用.apply和.call,但对于其他网站,如纽约时报和Netflix,只有.call可以使用 - 我猜测这是jQuery版本引起的差异,但有点困惑,因为numbers.div总是返回页面上所有div元素的数组,所以我认为它应该始终有效。如果能解释一下就好了,因为我仍在掌握.call和.apply的概念 - 我总是参考Douglas Crockford的书,但他实际上并没有详细介绍.apply和.call。
2个回答

4

.apply需要你将参数作为数组传递。

所以

myApp.hide.call(numbers, numbers.div)

应该与之前的内容相同

myApp.hide.apply(numbers, [numbers.div])

但是,在你的myApp.hide函数中,没有this,因此.call.apply的第一个参数可以是任何其他值,不会有影响。


谢谢xdazz,但为什么它在一些网站上可以工作而在其他网站上不行,这让我感到困惑,如果.call返回一个数组,为什么它仍然能够工作 - .call是否仍然适用于数组,而.apply只适用于数组,使用其中一个的优势是什么? - James Daly
1
.apply使用数组作为第二个参数,并将该数组中的所有内容作为参数传递给函数。另一方面,.call将第二个参数和之后的所有参数作为参数传递给函数。 - Kevin B
@JamesDaly 不是的,只需要检查签名,foo.call(obj, param1, param2, ...)foo.apply(obj, [param1, param2, ...]) - xdazz
啊,我想我终于明白了。你可以在 .call 中使用多个参数,但是在 .apply 中,你只需将这些参数存储为 JS 数组即可。我没有意识到你可以利用 .call 的多个参数。再次感谢 xdazz 和 Kevin B。我猜我仍然有点困惑,为什么它在某些网站上有效,而在其他网站上无效。我确定这与 jQuery 的版本有关,但现在我知道为什么 .call 比 .apply 更有效了。 - James Daly

2
call/apply的威力在于你想让被调用函数中的this指向哪个上下文。因为第一个参数决定了它将是什么。它们很好地说明了在JavaScript函数中,函数何时/在哪里被调用并不重要,而是如何调用。(所以在您的实例中,this将是numbers)。
无论如何,.apply().call()都能正常工作,它们的第二个参数实际上是可选的。
就像每个人所说的那样,它们之间唯一真正的区别在于您是否想将参数作为数组(数字数组[],而不是关联数组{})传递。 .apply(contextYouWant,[oneParam,twoParam,etc]); 或者在.call()的情况下,您单独传递参数。 .call(contextYouWant,oneParam,twoParam,etc);

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