2017-05-12 42 views
-1

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

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

,而不是

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

后者给了我在Firefox中一个TypeError this.trigger is not a function,但显然它是一个功能,因为typeof $('#selector').focus是“功能。”这里发生了什么?

+0

可能会有帮助http://stackoverflow.com/questions/23640755/why-does-settimeout-require-anonymous-function-to-work –

回答

3

这是因为this问题。每MDN documentation:由setTimeout()执行

代码从单独的执行上下文从中setTimeout被调用的函数调用。用于为被叫功能设置this关键字的常用规则适用,如果您未在呼叫中设置this或使用bind,则它将默认为非严格模式下的全局(或window)对象,或者严格为undefined模式。它不会与调用setTimeout的函数的这个值相同。

在JavaScript中,有一个“执行上下文”的概念,它是保存关于当前正在执行的内容的上下文的上下文。有一个全局执行上下文,当一个函数被调用时,会创建一个新的执行上下文。 this值取决于执行上下文,并根据当前执行上下文进行设置。由于setTimeout在调用目标函数时创建了新的执行上下文,因此this不代表DOM中的jQuery对象,而是全局对象(因为它是默认的,或者在严格模式下未定义)。因此,当jQuery内部调用this.trigger时,它试图调用不存在的window.trigger

尝试使用Function#bind其中明确设置this值:

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

或者,瑞安提到:

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

当然,你可以,如斜视提到的,使用arrow function来代替,该比使用bind和更惯用的更快:

setTimeout(() => $('#selector').focus(), 100); 
相关问题