Function.prototype
同时包含call
和apply
,可用于应用函数。今天,我打算使用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
这就是我已经掌握的这一点。我无意将其用于任何事情 - 这首先是一个诚实的错误 - 但我很想知道实际发生了什么,并希望你们中的一个大师可能会有答案。
为什么call
和apply
表现得这样?
答案 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);
}
所有功能都使用相同的call
和bind
方法。 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
。