2012-03-01 85 views
8

说我有一个简单的函数,警报消息:为什么这个封闭工作?

function callMessage(msg){ 
     alert(msg); 
    } 

现在,当我这样称呼它的话,它不工作。抛出错误“哎没有定义”

function sayHi(){ 
     var hey = "hi there" 
     setTimeout("callMessage(hey)", 1000); 
    } 
    sayHi(); 

但是,当我把它叫做一个匿名函数内部它的工作:

function sayHi(){ 
     var hey = "hi there" 
     setTimeout(function(){callMessage(hey);}, 1000); 
    } 
    sayHi(); 

为什么是“哎”变量,当我把它里面的唯一可见匿名函数?

+1

我也尝试这个; '的setTimeout( “VAR哎= '您好'; callMessage(嘿嘿)”,1000);' – mindandmedia 2012-03-01 15:49:13

+0

如果我是你,我会读一些类似 - http://www.digital-web.com/articles/scope_in_javascript/ – 2012-03-01 15:49:31

回答

14

在第一个示例中,在之后,计算代码计时器已过期,并且当前范围已保留。 hey在那个时候是未定义的。

第二个示例 - 使用setTimeout的正确方法 - 使用调用setTimeout()时创建的匿名函数。这个匿名函数还会接收当前范围的副本。

+0

在第二个例子中,封闭体在此之前不会被评估。 – sepp2k 2012-03-01 15:51:23

+2

直到晚些时候它才被执行。第一个*字面*评估('eval()'),没有提示使用哪个范围,因为它的“只是一个字符串”。 – 2012-03-01 15:52:49

+0

这很有道理。我不知道匿名函数有它的父范围的副本 – levi 2012-03-01 16:03:31

6

“callMessage(嘿)” 是一个字符串,而不是一个封闭。它会在超时运行时进行评估,此时变量hey不在范围内。

3

这是正常的。

第二个示例创建我们称之为夹具,这是一个执行环境。嘿变量变量被保存为由内存中的匿名函数使用。

在你的第一个例子,哎变量不会被保存在一个固定装置(因为JavaScript不能知道你将使用后的变量),因此不能被检索时,该字符串评估