9

每次我在 JavaScript 中声明回调时都必须手动设置对象的范围,这令人沮丧,但这是不争的事实。我想知道是否可以通过将 [mycallback].apply 作为回调传递,并将范围对象作为参数传递来做到这一点,如下所示:

var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(f.apply, 1000, o);

据我所知,这应该以 o 作为范围调用 f,但 Chrome 却给了我“未捕获的 TypeError:Function.prototype.apply 在 [object DOMWindow] 上被调用,这是一个对象而不是函数”。为什么这不起作用?

4

3 回答 3

5

出于同样的原因,您首先需要“设置范围”。只有apply函数被发送到setTimeout,它与函数的关联f丢失。因此,Javascript 将全局对象 , 分配windowthis,就像在任何其他情况下一样。

有趣的是apply,虽然是本机函数,但在某些方面并不特殊或神奇,并且在this变量设置中的行为方式与用户定义的函数一致。

于 2011-03-25T00:13:12.323 回答
4

@MooGoo 的回答是正确的,但也许需要更多解释。

当你像这样调用函数applyf

f.apply(ctx, args);

...然后你applyf.

但是当您传递对apply函数的引用时,如下所示:

setTimeout(f.apply, 1000, o);

...这就是你所做的一切:传递对 function 的引用f.apply。这相当于通过,Function.prototype.apply因为:

console.log(f.apply === Function.prototype.apply); // true

与 的任何连接都将f丢失window.setTimeout。它接收对 的通用apply函数的引用Function.prototype。而已。没有上下文。

因此,与未设置显式上下文的任何其他情况一样,apply函数window作为其上下文对象被调用。

于 2011-03-25T00:42:09.880 回答
-1

试试这个:

var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(function(){f.apply(o)}, 1000);

为我工作。

设置超时需要一个函数。但是由于 apply 是一个内置函数,你看不到它背后的本机代码,它可能不能充当“函数”对象。

于 2011-03-25T00:11:58.447 回答