为什么我必须在setTimeout中包装函数?

时间:2017-05-12 20:07:12

标签: javascript jquery

为什么我要写

setTimeout(function() { $('#selector').focus() }, 100);

而不是

setTimeout($('#selector').focus, 100);

后者在Firefox中给我一个TypeError this.trigger is not a function,但显然它是一个函数,因为typeof $('#selector').focus是“函数”。这是怎么回事?

1 个答案:

答案 0 :(得分:3)

这是因为this问题。每MDN documentation

  

setTimeout()执行的代码从单独的执行上下文调用到调用setTimeout的函数。设置被调用函数的this关键字的常规规则适用,如果您未在调用中设置this或使用bind,则默认为全局(或{{ 1}})非严格模式下的对象,或严格模式下为window。它与调用undefined的函数的此值不同。

在JavaScript中,有一个"执行上下文"的概念,它们是保存当前正在执行的内容的信息的上下文。这是一个全局执行上下文,当调用一个函数时,会创建一个新的执行上下文。然后,setTimeout值取决于执行上下文,并根据当前执行上下文进行设置。由于this在调用目标函数时创建了一个新的执行上下文,setTimeout不代表来自DOM的jQuery对象,而是全局对象(默认情况下,或严格模式下未定义) 。因此,当jQuery在内部调用this时,它会尝试调用不存在的this.trigger

尝试使用明确设置window.trigger值的Function#bind

this

或者,正如瑞安提到的那样:

setTimeout($('#selector').focus.bind($('#selector')), 100);

当然,你可以像斜视所提到的那样使用arrow function,这比使用setTimeout($.fn.focus.bind($('#selector')), 100); 和更惯用的更快:

bind