2015-06-09 18 views
4

这些是两个相同的代码;但第一个正常工作:`setTimeout`,通过字符串传递,返回错误

function dismiss(obj) {setTimeout(function() {obj.style.display = "none";}, 20);} 

,而第二个返回error: obj is not defined

function dismiss(obj) {setTimeout('obj.style.display = "none"', 20);} 

为什么会这样呢?
P.S:An example

+1

我猜是因为它没有捕获闭包并在全局范围内执行。 –

+2

_Why为什么这么做?_ - 因为在第一个版本中,匿名函数创建一个闭包,因此在本地作用域中保留对“obj”的引用,而第二个在全局对象的作用域中运行。 – CBroe

+0

其实这两个工作适用于我在Firefox 38.0.5 – AlliterativeAlice

回答

4

答案在于closures,or more in depth

在第一个示例中,创建匿名函数时将捕获obj变量。当运行该功能时,捕获的obj参考用于访问style,该工作正常。

在第二

然而,没有闭合,因为字符串是通过eval运行内部setTimeout其上Mozilla documentation如所述的,将全局上下文内执行:

字符串文本中被评估全局上下文,因此setTimeout()被调用的上下文中的局部符号在字符串被评估为代码时将不可用。

在全球范围内不包含obj变量,这导致了“没有定义”错误。

+0

闭包的更详细解释:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures –

+0

@FelixKling,谢谢,认为应该有更详细的解释。 – crazyhatfish

+0

不错。比我的答案更清楚。 – Lambart

2

obj只存在于dismiss()功能在它的范围和一切。第一条语句定义了一个函数,所以它可以引用它。第二个语句在该范围之外执行,不能引用它。

-6

正确的代码应该是这样的:

function dismiss(obj) {setTimeout(obj.style.display = "none", 20);} 

因为你在第一个和最后的obj.style.display = "none"添加'因此,它将成为一个字符串。

+1

这并不回答这个问题这是错误的。像那些未包含在函数中的语句会立即执行或评估。 – Xufox

+1

此外,这就像是传递''none''作为第一个参数。然而,'none'不是一个函数或没有定义。 – Xufox

1

documentation

Code executed by setTimeout() is run in a separate execution context to the function from which it was called. As a consequence, the this keyword for the called function will be set to the window (or global) object; it will not be the same as the this value for the function that called setTimeout.

在两个示例中,超时码的范围是全球范围内,或window

在第一个示例中,上下文无关紧要,因为obj.style.display在触发超时之前不进行评估。那时候,obj有最初传递给dismiss的任何值,并且一切正常。

在第二个示例中,代码立即执行,其中在全局window范围内的obj未定义(或者如果已定义,则此时不是您所期望的),因此您已生成此代码代码:

function dismiss(obj) {setTimeout(function() { undefined = "none" }, 20);}