JavaScript 作用域和闭包

IT技术 javascript scope closures
2021-03-14 17:17:21

我正试图围绕闭包(某处有一个笑话)而我遇到了这个:

(function () { /* do cool stuff */ })();

这是如何运作的?将函数放在括号中的目的是什么?为什么后面的括号是空的?

6个回答

这一点是在很酷的东西中声明的任何变量都不会在全局命名空间中创建。javascript 中的任何函数都会创建这样的作用域。假设您有一些想要运行的 javascript。如果你这样做:

var b = 1; 
// stuff using b

而其他一些代码使用 b,它将获得您剩余的value。(或者,更糟糕的是,如果其他一些代码在您的代码运行之前设置了 b,然后尝试获取其旧值,那么您会在此期间更改它。)

另一方面,如果您有以下代码,它声明然后调用 a 函数:

function a() { 
     var b = 1;
}

a();

而其他一些代码稍后会使用 b,它不会看到您的值,因为 b 是函数的本地值。当然,这样做的问题是您仍在创建全局名称 - 在这种情况下为“a”。所以,我们想要一个没有名字的函数——这就是为什么你得到你描述的代码。它声明了一个没有名字的函数,然后调用它。

不幸的是,你不能只说:

function() { ... }()

因为这将被解析为函数声明语句,然后是语法错误。通过将函数声明括在括号中,您可以获得一个函数表达式,然后可以调用它。您可以像任何其他函数表达式(如上面的 a)一样调用它,使用第二组括号。例如,如果函数接受参数,您可以将它们传递到那里:

(function(a) { ... })(1)

这会创建一个函数,调用它,然后丢弃它。

如果你这样看可能会更清楚:

var throwaway = function(){
    // do cool stuff
};
throwaway();

这样做是为了创建一个私有命名空间。函数中的代码可以有函数和变量,不用担心与页面加载的其他代码冲突。

嗯,是的。这就是为什么它通常用匿名函数来完成。我只是使用了一个命名函数来展示一个更熟悉的形式,它做同样的事情。
2021-04-16 17:17:21
jder 有更好的答案,对于那些迟到的人。
2021-04-21 17:17:21
jder 扩展了我对闭包的理解,但 Matthew 简短而甜蜜地回答了我的 3 个问题。谢谢!
2021-04-21 17:17:21
@Peter Bailey - 我的意思是 throwaway 中的变量不会发生冲突,但全局名称“throwaway”可能会发生冲突。
2021-04-26 17:17:21
当然,除非您与函数名称冲突。
2021-05-03 17:17:21

我最近刚看到这个帖子。这种类型的函数定义和调用称为自调用函数

(function(){  //code })();

函数内的代码将在其定义后立即执行。

该构造意味着声明一个匿名函数并立即运行它。您将代码放在函数体中的原因是因为您在其中定义的变量对于函数而言仍然是局部的,而不是作为全局变量。但是,它们仍然对这个函数中定义的闭包可见。

函数周围的括号清楚地表明该函数是一个表达式。后面的括号是对函数的调用。

请注意,该函数没有名称。