Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript (JS)闭包是否需要函数内部的函数_Javascript_Closures - Fatal编程技术网

Javascript (JS)闭包是否需要函数内部的函数

Javascript (JS)闭包是否需要函数内部的函数,javascript,closures,Javascript,Closures,我对闭包的固有概念有点困难。我明白了基本的想法,但问题是:从技术上讲,我认为每个Javascript函数中都有一个“闭包”。引用维基百科: 在计算机科学中,一种闭包(也称为词汇闭包、函数闭包) 或函数值)是带有引用的函数 该函数的非局部名称(自由变量)的环境。 这样的函数被称为其自由变量的“闭合” 因此,由于可以在函数中定义变量,它们与代码的其余部分是“封闭的”,因此我将其视为封闭的。因此,据我了解: (function(){var a = 1;}()) 是闭包的一个(不是很有用)示例。或者见

我对闭包的固有概念有点困难。我明白了基本的想法,但问题是:从技术上讲,我认为每个Javascript函数中都有一个“闭包”。引用维基百科:

在计算机科学中,一种闭包(也称为词汇闭包、函数闭包) 或函数值)是带有引用的函数 该函数的非局部名称(自由变量)的环境。 这样的函数被称为其自由变量的“闭合”

因此,由于可以在函数中定义变量,它们与代码的其余部分是“封闭的”,因此我将其视为封闭的。因此,据我了解:

(function(){var a = 1;}())
是闭包的一个(不是很有用)示例。或者见鬼,即使只是这样:

function(){var a = 1;}
但是,我认为我的理解可能是错误的。其他人告诉我,要使某个东西成为一个闭包,它必须保持一个状态,因此,因为除了代码之外没有任何东西保持不变,所以它实际上不是一个闭包。这表明您需要:

function(foo){foo.a = 1;}(bar); // bar.a = 1
甚至(为了确保不可修改):

所以,从技术上讲(我知道有几个例子实际上毫无意义,但是)上面哪个例子实际上是闭包的例子。闭包是否必须是一个空间(即JS函数内部),可以存储外部无法访问的变量,或者持久性是闭包定义的关键部分

编辑 刚刚注意到堆栈溢出上“closures”标记的wiki定义:

闭包是指(闭包)的一级函数 定义它的范围中的变量。如果关闭仍然有效 在其定义范围结束后存在,它关闭的变量 也将继续存在

虽然SO wiki当然不是最终的权威,但第一句话似乎与我对这个词的理解相关。第二句话建议如何使用闭包,但这似乎不是一个要求

编辑#2
如果从这里不同的答案、维基百科的答案和标签答案中不清楚,那么“关闭”一词的含义似乎也没有明确的共识。所以,虽然我很欣赏到目前为止所有的答案,如果你按照作者对闭包的定义,它们都是有意义的,但我想我真正想要的是。。。该词是否有任何实际的“权威”定义(如果有,它如何应用于上述所有内容)?

JavaScript(和其他语言)中的闭包用于控制和定义范围。不需要在函数中定义函数,就可以将其“限定”为闭包。函数的主体是闭包。更常见的用法之一是声明一个局部作用域变量,该变量将成为您将返回的其他对象或函数的私有或隐藏成员,但这不是一条严格的规则。

您被错误地假设“closure”一词来自何处而误入歧途

在语言理论环境中,闭包的要点是函数可以引用在其自身定义之外声明的变量。它是否有内部变量,或者内部变量从外部看不到,这无关紧要。换句话说,它是关于从函数到其定义环境的观察,而不是从函数外部观察

那为什么要用这个奇怪的词呢?请看上一个示例中的函数:

bar.baz = function() { return a }
此函数包含变量
a
,该变量未在函数体中定义。它是函数体的“自由”变量,在定义中有点像“洞”。我们不能在不知道(通过某种无关的方式)主体中标识符
a
所指的变量的情况下执行函数。在运行时形成闭包将此“打开”函数体与相应变量的引用配对,从而关闭定义中的漏洞。这就是这个名字的由来

(如果你想得到完全技术性的解释,基本概念是lambda演算中的“封闭”项,这意味着没有自由变量。只有封闭项才有独立的含义。封闭是a的组合(通常编译)非封闭的源代码片段,以及上下文信息,这些信息使其表现为一个封闭的术语,因此是可执行的)

附录:常用的成语

function() {
   var blah;
   // some code here
}();

关键不是要得到一个闭包(当然,你会得到一个闭包,但它不会给你带来任何有趣的事情),而是要为
blah
变量创建一个局部范围。局部作用域在概念上与闭包完全不同——事实上,除了Javascript之外,大多数C-lookalike都会在每个
{}
块上创建它们,而它们可能有闭包,也可能根本没有闭包。

从技术上讲,您的示例都不是闭包。(但在某些情况下,第四个样本可以被归类为第四个样本,见下文)

闭包是一种数据结构,它结合了对函数的引用和声明时活动的调用帧(或作用域)的非空列表

闭包是通过执行一些代码创建的,这些代码包含使用外部作用域变量的函数声明。在这种情况下,运行时在执行代码时,不仅必须创建对函数的引用,还必须创建闭包结构-函数引用和对其当前环境的引用-包含已使用外部变量的调用帧列表

例如,在“我的调用”中,调用帧在堆栈上被替换-当您从函数退出时,它的调用帧(包括它使用的变量集合)将从堆栈中清除。在我的例子中,当VM满足函数声明指令并且该函数被(编译器)标记为使用外部变量的函数时,就会创建闭包。在这种情况下,保存已用变量的当前调用帧链从堆栈移动到堆-
function() {
   var blah;
   // some code here
}();
function(foo){  
   var a = 1; 
   bar.baz = function() { return a; }; 
}