undefined
”,而在第二个示例中,它是可访问的并且输出“Nishant
”我无法弄清楚它是如何工作的!
(function(){
var name = "Nishant";
arguments[0]();
})(function(){console.log(name);});
输出:(空字符串)
(function(){
var name = "Nishant";
(function(){console.log(name);})()
})();
输出:Nishant
答案 0 :(得分:2)
我无法弄清楚它是如何工作的!
JavaScript有lexical scope。这意味着范围取决于在源代码中定义函数的位置(与动态范围不同,其中范围是在运行时调用函数时确定的。)
让我们为您的函数添加一些名称,以便我们更容易地引用它们:
(function foo(){
var name = "Nishant";
arguments[0]();
})(function bar(){console.log(name);});
在这种情况下,bar
在<{1}}的之外定义,因此无法访问foo
内定义的变量。事实上,在创建foo
时,bar
内的变量name
甚至还不存在,因为foo
尚未执行。
当你没有内联定义时,可能会更容易看到:
foo
这看起来可能比较熟悉,我打赌你不会指望function bar(){console.log(name);}
(function foo(){
var name = "Nishant";
arguments[0]();
})(bar);
内的name
与bar
内的name
有任何关系,对吗?
在另一种情况下,
foo
您在(function foo(){
var name = "Nishant";
(function bar(){console.log(name);})()
})();
的中定义了bar
。 foo
也位于name
内,因此foo
可以访问该变量(词法范围+闭包)。
答案 1 :(得分: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