【问题标题】:Using Function.prototype.apply to set javascript callback scope使用 Function.prototype.apply 设置 javascript 回调范围
【发布时间】:2011-07-22 13:51:50
【问题描述】:

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

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

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

【问题讨论】:

  • 到底是谁用反对票轰炸了我们所有的答案?
  • @Travis - 我认为你的回答很好;它只是没有抓住重点。 @MooGoo 的回答实际上说明了与f 的关联丢失了,这是最好的答案。
  • 任何怀疑你可以将原生函数作为参数传递给其他函数的人都应该试试这个:Function.prototype.apply.apply.call(Function.prototype.apply, function(t) { alert(t) }, [this, ["test"]]);
  • @lwburk 是的,你是对的。我寻求解决方案,而不是“为什么”
  • 您可能想要f.bind(o)(并非在所有浏览器中都可用)。

标签: javascript scope apply


【解决方案1】:

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

当你像这样在f 上调用函数apply 时:

f.apply(ctx, args);

...那么您将在f 的上下文中执行apply

但是当你将 apply 的引用传递给函数时,像这样:

setTimeout(f.apply, 1000, o);

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

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

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

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

【讨论】:

    【解决方案2】:

    试试这个:

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

    为我工作。

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

    【讨论】:

    • 说“将参数传递给 setTimeout 非常粗略”到底意味着什么?它的行为是明确定义的。
    • eek,对我来说有点夸张。通过观察,它定义明确,粗略,因为它的行为与您预期的不同。
    • 我得到一个控制台日志 3。这如何改变上下文?
    【解决方案3】:

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

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

    【讨论】:

    • 哦!正确的。呃。这很有意义。
    猜你喜欢
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多