Javascript 为什么';(函数a(){})和#x27;不放';a';进入全局对象?
当我问另一个问题时,我用这个模式递归调用函数:Javascript 为什么';(函数a(){})和#x27;不放';a';进入全局对象?,javascript,function,scope,window,global,Javascript,Function,Scope,Window,Global,当我问另一个问题时,我用这个模式递归调用函数: (function() { // ... if(should_call_again) arguments.callee(); })(); 这起作用了。我得到的反馈是,命名函数也有效: (function func() { // ... if(should_call_again) func(); })(); 然而,使用这种技术,window.func是未定义的,这让我感到惊讶 如果我简单地说,我的问题是:为什么下面
(function() {
// ...
if(should_call_again) arguments.callee();
})();
这起作用了。我得到的反馈是,命名函数也有效:
(function func() {
// ...
if(should_call_again) func();
})();
然而,使用这种技术,window.func
是未定义的
,这让我感到惊讶
如果我简单地说,我的问题是:为什么下面的说法是正确的
function a() {}
typeof window.a; // "function"
(function b() {})
typeof window.b; // "undefined"
b
仍然可以在b
内部访问。所以看起来像是()
创建了另一个作用域,但事实并非如此,因为只有函数才能创建另一个作用域,而我只是将其包装在()
中
那么,为什么将函数包装在
()
中不会将函数放入全局对象中呢?因为您编写的不是函数声明,而是函数表达式
函数表达式中定义的函数只在将它们赋给变量时存储在某个地方;你没有那样做;你只是马上打电话
在[非常松散的!]意义上,您可以将函数声明视为函数表达式赋值的一种特殊形式:
function a() {}
// vs:
var a = function() {};
这仍然不是一个严格准确的比较,但它可能有助于理解函数声明是一种特殊的东西。您似乎忽略了一个细微的区别,而不是将函数定义为:
(function b () { });
它实际上是这样写的:(注意末尾的parenthase的额外集合)
当您编写这样的函数时,它会立即被调用,但仍然有自己的作用域。我不知道为什么该函数可以通过其名称访问,但将定义包装在
()
中会使其成为函数表达式,即使它们有名称,它不会在当前作用域中创建符号。它可能是经过计算的,因为它没有分配给变量,所以不会出现在该作用域中。在函数调用时创建的激活对象可能通过其名称引用函数本身。即使将函数赋给变量,也可以从函数内部通过其名称访问该函数。有关为什么可以通过函数内部的名称访问该函数的解释,请参见以下答案:@Felix Kling:我想这回答了我的问题<代码>。。。FunctionExpression中的标识符无法从引用,并且不会影响包含FunctionExpression的范围。谢谢。不过,我不确定我是否理解正确<代码>(函数b(){console.log(1)})代码>不记录任何内容。
(function b () { }());