为什么应用调用函数没有传递正确的参数

Why does applying the call function not pass the correct argument?

本文关键字:参数 应用 调用 函数 为什么      更新时间:2023-09-26

Function.prototype同时具有可用于应用函数的callapply。今天,我打算用apply来做一些事情,但我设法偷偷输入了一个拼写错误:

function foo(a) { console.log('foo', a) }
foo.call.apply(null, [1])

我花了一段时间才意识到,我已经设法(大概是在某种影响下(在.apply之前写了.call。然而,令我惊讶的是,这将抛出一个TypeError:

> function foo(a) { console.log(a) }
undefined
> foo.call.apply(null, [1])
TypeError: object is not a function
    at repl:1:10

这让我有一段时间目瞪口呆,直到我想这一定是因为call函数绑定到了null。所以我想,让我们试着把它绑定到foo上,看看会发生什么:

> foo.call.apply(foo, [1])
foo undefined

啊,不完全是我所期望的。函数已明确应用,但由于某种原因,参数aundefined。我似乎想不通。删除.call显然如预期一样有效:

> foo.apply(foo, [1])
foo 1

因为我现在真的很好奇,我尝试了相反的方法:call apply函数:

> foo.apply.call(foo, 1)
foo undefined

这是我所能做到的。我无意将其用于任何事情——这首先是一个诚实的错误——但我很好奇到底发生了什么,并希望你们中的一位大师能给出答案。

为什么callapply会这样?

foo.call.apply(null, [1])

这调用Function.prototype.call并将其上下文设置为null,并传递1作为参数。

所以,就像您所做的:Function.prototype.call(1);,上下文(this(设置为null。它试图运行nullcall函数,所以这就是为什么您得到"对象不是函数"。

foo.call.apply(foo, [1])

这不起作用,因为call的参数是如何设置的。您正在调用Function.prototype.call(1);,上下文(this(设置为foo。就像你做的一样:foo.call(1)

如果你想连锁callapply,你必须这样做:

foo.call.apply(foo, [null, 1]);

设置.call函数的上下文,然后设置它的两个参数。

让我们从一个信息更丰富的"foo"函数开始:

function log() {
  console.log('args: ', arguments, ''nthis: ', this);
}

所有函数都具有相同的callbind方法。log.call是一个函数,作为一个函数它具有与其他函数相同的apply方法。所以这两个是等价的:

log.apply.call === log.call
log.call === Function.prototype.call


调用此:

log.call.apply(null, [1])

与调用这个相同:

Function.prototype.call.apply(null, [1])

上面调用了window上的Function.prototype.call方法,将1作为唯一的参数传递。

这显然是非常错误的;call应该只用于函数,而不是窗口对象,并且传递给调用的第一个参数应该是执行范围,而不是1