2014-06-08 180 views
1

我起初认为看起来既自我调用函数,它们之间相同的唯一区别是第一个我想过去的回调函数,然后通过参数执行的对象,而在第二次做同样的事情通过使功能自我调用。现在就来访问父变量的点在第一个例子名为“undefined”,而在第二个例子是访问,并给予输出“Nishant”我无法弄清楚它是如何工作的!父函数变量访问

(function(){ 
    var name = "Nishant"; 
    arguments[0](); 

})(function(){console.log(name);}); 

输出:(空字符串)

(function(){ 
    var name = "Nishant"; 
    (function(){console.log(name);})() 
})(); 

输出:NISHANT

回答

1

的 “名称” 中的第一个版本是指全球window.name财产*,并且在第二个例子通过闭包的私人var名称。 window.name属性是可选的,并且默认为空字符串。

如果此属性不会发生存在你的第一个例子会抛出一个引用错误。

封闭在函数被宣布为范围内创建,而不是在一点上得到了打来电话,第一个例子函数声明是在全球范围内,在包装功能范围内的第二次。

window.name = "NoClosure"; 
(function(){ 
    var name = "Closure"; 
    arguments[0](); 
})(function(){console.log(name);}); //>"NoClosure" 

window.name = "NoClosure"; 
(function(){ 
    var name = "Closure"; 
    (function(){console.log(name);})(); //>"Closure" 
})(); 

如果您检查与console.dir()回调,你可以看到它有没有关闭,在这里的一个片段,如果你想测试它自己。

(function wrapper(){ 
    var isPrivate = "A closure could see me"; 
    console.dir(arguments[0]); 
})(function callback(){}); 

这里是另一个实验设置与2个封闭表示对函数的调用内部宣称函数能够得到一个封闭的,但它总是会传递它的函数的范围的关闭,它无法访问作为参数传递给的函数的作用域,稍后将其作为回调调用。

(function outerScope(){ 
    var outerVar = "in outer scope"; 
    (function innerScope(cb){ 
     var innerVar = "in inner scope"; 
     cb(); 
    })(function callback(){ 
     console.log(
      "outer:"+ typeof outerVar, 
      "inner:"+ typeof innerVar); 
     console.dir(arguments.callee); 
    }) 
})() 

*源https://developer.mozilla.org/en-US/docs/Web/API/Window.name

+0

Ref:http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/回调函数是闭包当我们将回调函数作为参数传递给另一个函数时,回调会在某些就像在包含函数中定义回调一样,指向包含函数的内部体。这意味着回调本质上是一个封闭。阅读我的详细信息,了解更多关于闭包的轻松理解JavaScript闭包。 –

+0

你可以给我(或者链接)一个回调函数的例子,该回调函数作为一个参数被传递给函数,因为我不能重现你所描述的函数。 – Winchestro

+0

好吧,我已经阅读了这两篇文章以及你对它的评论(这是你在这里写的东西的一个副本),并且仍然没有按照你的思路或重构任何回调关闭的情况。如果我愿意的话,这会让我的生活变得轻松许多,所以请给我一个提示,告诉我你是如何设法回调封闭的。 – Winchestro

2

我无法弄清楚它是如何工作的!

JavaScript有lexical scope。这意味着通过在函数的源代码内所定义的范围被确定(不像动态范围,其中当功能被称为在运行时确定的范围)。

让一些名字添加到您的功能,这样我们就可以更轻松地引用这些:

(function foo(){ 
    var name = "Nishant"; 
    arguments[0](); 
})(function bar(){console.log(name);}); 

在这种情况下bar定义foo,因此不能访问的foo内定义的变量。实际上,在创建bar时,foo中的变量name甚至还不存在,因为foo尚未执行。
也许是更容易地看到,当你不内联定义:

function bar(){console.log(name);} 

(function foo(){ 
    var name = "Nishant"; 
    arguments[0](); 
})(bar); 

这可能看起来比较熟悉,而且我敢打赌,你不会想到namebar有什么关系namefoo,右?


在其他情况下,

(function foo(){ 
    var name = "Nishant"; 
    (function bar(){console.log(name);})() 
})(); 

你定义bar内的fooname也在foo之内,因此bar可以访问该变量(词法范围+闭包)。

+0

+1好的答案,谢谢澄清。 – Winchestro

+0

可以肯定的是,对提交者提出的任何评论,我引用“回调函数是闭包当我们将回调函数作为参数传递给另一个函数时,回调会在包含函数的内部某处执行,就像回调是在包含函数中定义的“,因为他刚离开并且没有回答我的问题。对于回调来说,通过闭包传递给函数的作用域是不可能的。 – Winchestro

+0

没有。这只有当JS拥有动态范围时才可能,但事实并非如此。 –