为什么应用call函数不能传递正确的参数?

时间:2014-03-21 18:03:41

标签: javascript

Function.prototype同时包含callapply,可用于应用函数。今天,我打算使用apply来获取某些东西,但是却设法隐瞒了一些错字:

function foo(a) { console.log('foo', a) }

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

我花了一段时间才意识到我曾设法(可能是在某些事物的影响下)在.call之前写.apply。然而令我感到惊讶的是,这会引发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
嗯,不是我所期待的。该功能已明确应用,但参数a由于某种原因undefined。我似乎无法弄清楚这一点。删除.call显然可以按预期工作:

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

因为我现在非常好奇,所以我尝试了相反的方法:call apply函数:

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

这就是我已经掌握的这一点。我无意将其用于任何事情 - 这首先是一个诚实的错误 - 但我很想知道实际发生了什么,并希望你们中的一个大师可能会有答案。

为什么callapply表现得这样?

2 个答案:

答案 0 :(得分:3)

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

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

所以,就像你做的那样:Function.prototype.call(1);,上下文(this)设置为null。它试图运行call的{​​{1}}函数,这就是为什么你得到“对象不是函数”的原因。

null

由于foo.call.apply(foo, [1]) 的参数设置如何,这不起作用。您正在调用call,并将上下文(Function.prototype.call(1);)设置为this。就像你做的那样:foo

如果你想链接foo.call(1)call,你必须这样做:

apply

设置foo.call.apply(foo, [null, 1]); 函数的上下文,然后设置两个参数。

答案 1 :(得分:1)

让我们从更具信息性的'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])

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

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