每次在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]上被调用,它是一个对象,而不是一个函数”。为什么这不起作用?
答案 0 :(得分:5)
出于同样的原因,您需要首先“设置范围”。只有apply
函数被发送到setTimeout
,其与函数f
的关联将丢失。因此,Javascript会将全局对象window
分配给this
,就像在任何其他情况下一样。
值得注意的是apply
虽然是本机函数,但在某种程度上并不特殊或神奇,并且在this
的设置中以与用户定义函数一致的方式运行变量
答案 1 :(得分:4)
@ MooGoo的回答是正确的,但也许需要更多的解释。
当你在apply
上调用f
这样的函数时:
f.apply(ctx, args);
...然后您在apply
。
f
但是当你将apply
的引用传递给函数时,就像这样:
setTimeout(f.apply, 1000, o);
...这就是你所做的一切:传递对函数f.apply
的引用。这相当于传递Function.prototype.apply
,因为:
console.log(f.apply === Function.prototype.apply); // true
f
中与window.setTimeout
的任何连接都将丢失。它接收对apply
的通用Function.prototype
函数的引用。而已。没有背景。
因此,与未设置显式上下文的任何其他情况一样,调用apply
函数时将window
作为其上下文对象。
答案 2 :(得分:-1)
试试这个:
var f = function() { console.log(this.x); };
var o = {x: 3};
setTimeout(function(){f.apply(o)}, 1000);
适合我。
设置超时需要一个函数。但由于apply是一个内置函数,你无法看到它背后的本机代码,它可能不会充当“函数”对象。