首页 / 知识
关于函数式编程:什么是’闭包’?
2023-04-13 18:07:00

What is a 'Closure'?我问了一个关于咖喱和闭包的问题。什么是关闭?它与咖喱有什么关系? 可变范围 当您声明一个局部变量时,该变量有一个作用域。通常,局部变量只存在于声明它们的块或函数中。
如果我试图访问一个局部变量,大多数语言都会在当前范围内查找它,然后在父范围内查找,直到它们到达根范围为止。
当一个块或函数完成时,它的局部变量就不再需要了,通常会耗尽内存。 这就是我们通常所期望的工作方式。 闭包是一个持久的局部变量范围闭包是一个持久的作用域,即使在代码执行从该块中移出之后,它仍然保留着局部变量。支持闭包的语言(如javascript、swift和ruby)将允许您保留对某个范围(包括其父范围)的引用,即使在声明这些变量的块执行完毕之后,只要您在某个地方保留对该块或函数的引用。 作用域对象及其所有局部变量都与函数绑定在一起,并且只要该函数持续存在,它就会一直存在。 这给了我们功能可移植性。我们可以预期,当我们稍后调用函数时,在第一次定义函数时范围内的任何变量仍然在范围内,即使我们在完全不同的上下文中调用函数也是如此。 例如下面是一个非常简单的javascript示例,说明了这一点:
在这里,我定义了一个函数中的一个函数。内部函数可以访问所有外部函数的局部变量,包括 通常,当一个函数退出时,它的所有局部变量都会被吹走。但是,如果我们返回内部函数并将其分配给一个变量 注意变量 你也许可以猜到,当我调用 在没有闭包的语言中,当函数 在javascript中,变量 我将给出一个示例(在javascript中):
这个函数makecounter的作用是返回一个函数,我们称之为x,每次调用该函数时,该函数将按1计。因为我们没有给x提供任何参数,它必须记住计数。它知道在什么地方可以根据所谓的词法范围来找到它——它必须找到它定义的地方来找到值。这个"隐藏"值就是所谓的闭包。 下面是我的当前示例:
您可以看到,当使用参数a(即3)调用add时,该值包含在我们定义为add3的返回函数的闭包中。这样,当我们调用add3时,它知道在哪里找到执行加法的a值。 凯尔的回答很好。我认为唯一的补充说明是闭包基本上是创建lambda函数时堆栈的快照。然后,当重新执行函数时,在执行函数之前,堆栈将恢复到该状态。因此,正如Kyle提到的,当lambda函数执行时,隐藏值( 首先,与这里大多数人告诉你的相反,闭包并不是一个功能!那是什么?< BR>它是在函数的"环境上下文"(称为其环境)中定义的一组符号,使其成为一个封闭表达式(即,一个表达式,其中定义了每个符号并具有一个值,因此可以对其进行计算)。 例如,当您有一个javascript函数时:
它是一个封闭表达式,因为其中出现的所有符号都在其中定义(它们的含义很清楚),所以您可以对其进行评估。换句话说,它是独立的。 但是如果你有这样的功能:
它是一个开放式表达式,因为其中有尚未定义的符号。也就是说, 这个 例如,它可以全局定义:
或者它可以在包装它的函数中定义:
环境的一部分,在一个表达式中给了自由变量它们的含义,那就是闭包。之所以这样叫它,是因为它通过为所有自由变量提供这些缺失的定义,将一个打开的表达式转换为一个关闭的表达式,这样我们就可以计算它了。 在上面的例子中,内部函数(因为我们不需要它而没有给出名称)是一个开放表达式,因为其中的变量
现在,闭包是这个环境的一部分,它通过提供所有自由变量的定义来关闭内部函数。在我们的例子中,内部函数中唯一的自由变量是
环境中定义的其他两个符号不是该函数闭包的一部分,因为它不需要运行它们。不需要他们关闭它。 更多关于这背后的理论:https://stackoverflow.com/a/36878651/434562 值得注意的是,在上面的示例中,包装函数以值的形式返回其内部函数。从定义(或创建)函数的那一刻起,我们调用这个函数的那一刻就可以是远程的。特别是,它的包装函数不再运行,它在调用堆栈上的参数也不再存在:p这是一个问题,因为内部函数在调用时需要 这就是为什么人们经常混淆闭包这个词,把它当成可以对所使用的外部变量进行快照的特殊类型的函数,或者把用来存储这些变量供以后使用的数据结构。但我希望您现在理解,它们不是闭包本身——它们只是在编程语言中实现闭包的方法,或者是允许函数闭包中的变量在需要时存在的语言机制。关于闭包有很多误解(不必要的)使这个主题比实际更混乱和复杂。 闭包是可以引用另一个函数中的状态的函数。例如,在Python中,它使用闭包"inner":
为了有助于理解闭包,可以检查如何用过程语言实现闭包。这个解释将遵循方案中闭包的简单实现。 首先,我必须介绍名称空间的概念。在方案解释器中输入命令时,它必须计算表达式中的各种符号并获取它们的值。例子:
define表达式将值3存储在x的spot中,将值4存储在y的spot中。然后,当调用(+x y)时,解释器将查找命名空间中的值,并能够执行该操作并返回7。 但是,在方案中,有些表达式允许您临时重写符号的值。下面是一个例子:
let关键字的作用是引入一个新的名称空间,其中x值为5。你会注意到它仍然可以看到y是4,使得返回的值为9。您还可以看到,一旦表达式结束,x将恢复为3。从这个意义上讲,x被局部值暂时掩盖了。 程序语言和面向对象语言有类似的概念。每当在与全局变量同名的函数中声明变量时,都会得到相同的效果。 我们将如何实现这一点?一个简单的方法是使用链接列表-头部包含新值,尾部包含旧名称空间。当你需要查找一个符号时,你从头部开始,沿着尾部向下移动。 现在让我们跳到第一类函数的实现。或多或少,函数是一组指令,当函数在返回值中被调用时执行。当我们读入一个函数时,我们可以在后台存储这些指令,并在调用函数时运行它们。
我们将x定义为3,将plus-x定义为其参数y,再加上x的值。最后,我们在x被新x掩盖的环境中调用plus-x,这个环境值为5。如果我们只存储函数plus-x的操作(+x y),因为我们在x为5的上下文中,返回的结果是9。这就是所谓的动态范围界定。 然而,Scheme、CommonLisp和许多其他语言都有所谓的词汇范围——除了存储操作(+x y)之外,我们还将命名空间存储在那个特定的点上。这样,当我们查找值时,我们可以看到,在这个上下文中,x实际上是3。这是一个终结。
总之,我们可以使用一个链接列表来存储函数定义时命名空间的状态,允许我们从封闭范围访问变量,并提供我们在不影响程序其余部分的情况下本地屏蔽变量的能力。 这里有一个现实世界的例子说明为什么闭包会踢屁股…这完全是我的javascript代码。让我举例说明。
以下是您将如何使用它:
现在假设您希望播放延迟,例如在运行此代码段后5秒。好吧,使用EDOCX1[0]很容易,而且它是关闭的:
当使用 如果没有闭包,您将不得不在函数外部以某种方式维护这些变量的状态,从而将函数外部的代码与逻辑上属于函数内部的内容一起丢弃。使用闭包可以大大提高代码的质量和可读性。 DR 闭包是一个函数,它的作用域被分配(或用作)一个变量。因此,名称闭包:作用域和函数与任何其他实体一样被封闭和使用。 深入的维基百科风格解释根据维基百科的说法,结束语是:
那是什么意思?我们来看看一些定义。 我将使用以下示例解释闭包和其他相关定义:
基本上,这意味着我们可以像其他实体一样使用函数。我们可以修改它们,将它们作为参数传递,从函数返回它们,或者为变量分配它们。从技术上讲,他们是一流的公民,因此得名:一流的职能。 在上面的示例中, 名称绑定是为了找出变量(标识符)引用的数据。作用域在这里非常重要,因为它将决定如何解析绑定。 在上面的示例中:
在匿名函数的作用域内, 正如维基百科所说,范围:
有两种方法:
有关更多解释,请查看这个问题并查看维基百科。 在上面的例子中,我们可以看到javascript在词法上的作用域,因为当解析 在我们的示例中,当我们调用 现在,您应该了解闭包以及它们的行为,这是JavaScript的基本部分。 咖喱哦,您还了解了curring的含义:使用函数(闭包)传递操作的每个参数,而不是使用一个带有多个参数的函数。 不包含自由变量的函数称为纯函数。包含一个或多个自由变量的函数称为闭包。
SRC:https://leanpub.com/javascriptallongesix/read leanpub auto如果没有自由变量的函数是纯闭包,则为不纯闭包。 在正常情况下,变量受范围规则约束:局部变量仅在定义的函数内工作。关闭是为了方便而暂时打破这一规则的一种方式。
在上面的代码中, 现在,如果将生成的匿名函数放入一个函数变量中。
foo将打破正常范围规则,并开始在内部使用4。
返回12。 简而言之,函数指针只是指向程序代码库中某个位置的指针(如程序计数器)。而闭包=函数指针+堆栈帧。 . 闭包是JavaScript中的一个特性,函数可以访问自己的作用域变量、访问外部函数变量和访问全局变量。 即使在外部函数返回之后,闭包也可以访问其外部函数范围。这意味着闭包可以记住并访问其外部函数的变量和参数,即使在函数完成之后也是如此。 内部函数可以访问在其自身范围、外部函数范围和全局范围中定义的变量。外部函数可以访问其自身作用域和全局作用域中定义的变量。
输出为20,其内部函数自身变量、外部函数变量和全局变量值之和。 这是另一个真实的例子,使用了一种在游戏中很流行的脚本语言——Lua。我需要稍微改变库函数的工作方式,以避免stdin不可用的问题。
当这段代码完成它的作用域(因为它是本地的)时,旧的"dofile"的值将消失,但是该值已包含在一个闭包中,因此新的重新定义的dofile函数可以访问它,或者更确切地说,与函数一起存储的副本作为"upvalue"。 当前:它允许您通过只传递函数参数的一个子集来部分地评估函数。考虑一下:
闭包:闭包只不过是访问函数范围之外的变量。必须记住,函数或嵌套函数内的函数不是闭包。当需要访问函数范围之外的变量时,总是使用闭包。
如果您来自Java世界,可以将闭包与类的成员函数进行比较。看看这个例子
函数 闭包每当我们在另一个函数中定义了一个函数时,内部函数就可以访问声明的变量。在外部功能中。闭包最好用示例来解释。在清单2-18中,可以看到内部函数从外部范围。外部函数中的变量已由内部函数关闭(或绑定)。因此这个词关闭。这个概念本身很简单,也相当直观。
来源:http://index of.es/varos/basarat%20ali%20syed%20(auth.)-beginning%20node.js apress%20(2014).pdf 请看下面的代码,以更深入地了解闭包:
这里将输出什么?由于关闭, 那么它将如何解决呢?答案如下:
让我简单解释一下,当一个函数创建时,直到它在第1个代码中调用了5次循环,但没有立即调用,所以当它调用时,也就是在1秒之后,这是异步的,所以在这个for循环完成之前,将值5存储在var i中,最后执行 这里介绍如何使用IIFE解决问题,即立即调用函数表达式
有关更多信息,请理解执行上下文以了解闭包。
=>更多说明: 在内存中,当for循环执行以下图片制作: 循环1)
循环2)
循环3)
循环4)
循环5)
这里我不执行,然后在完成循环后,var i将值5存储在内存中,但是它的作用域在它的子函数中总是可见的,所以当函数在 所以要解决这个问题,请使用上面解释的IIFE。 来自LuA.Org:
|
最新内容
相关内容
使用Python的toolz库开始函数式编
使用Python的toolz库开始函数式编程,代码,函数,培训,位置,参数,字典,顺序,操作,结果,测试,toolz库允许你操作函数,使其更容易理解,更容易测试代python之什么是函数式编程?
python之什么是函数式编程?,系统,概念,项目,大规模,状态,数据,培训,函数,语言,副作用,函数式编程(简称FP)是一种编程范式,其中最基本的元素是python中闭包的实质
python中闭包的实质,代码,数据,函数,名字,情况,变量,地址,位置,地方,培训,python中闭包这个概念好难理解,身边朋友们好多都稀里糊涂的,希望写下python闭包的定义
python闭包的定义,信息,环境,函数,状态,培训,变量,外层,定义,内部,作用,如果在一个内部函数中,引用了外部非全局作用域中的变量,那么这个内部函Python的函数式编程与闭包
Python的函数式编程与闭包,代码,灵活,函数,数据,概念,变量,培训,不了,工业,环境,函数式编程 函数式编程这个概念我们可能或多或少都听说Python什么是函数式编程?
Python什么是函数式编程?,状态,技术,代码,系统,数据,函数,工作,培训,地方,边界,函数式编程使用一系列的函数解决问题。函数仅接受输入并产生Python函数式编程指南之生成器
Python函数式编程指南之生成器,暂停,生成器,位置,异常,代码,简介,工作,培训,函数,方法,生成器(generator)1.生成器简介首先请确信,生成器就是python函数式编程到底是个什么
python函数式编程到底是个什么,状态,函数,培训,名称,概念,术语,指数,数据,命令,变量,一概念(函数式编程)函数式编程是一种编程范式,我们常见的Python 函数式编程概述
Python 函数式编程概述,状态,代码,技术,数据,系统,函数,地方,工作,培训,边界,1.1.什么是函数式编程?函数式编程使用一系列的函数解决问题。函python 中闭包,闭包的实质
python 中闭包,闭包的实质,代码,函数,数据,情况,名字,变量,地址,地方,位置,培训,请大家跟我理解一下,如果在一个函数的内部定义了另一个函数,外python的闭包函数是什么
python的闭包函数是什么,代码,工作,函数,培训,程序,外部,个数,变量,嵌套,赋值,python中的闭包,又称闭包函数或者闭合函数,其实和前面讲的嵌套函python声明变量
python声明变量,培训,代码,变量,赋值,字符串,类型,语句,函数,上面,声明,首先,在Python解释器中输入如下内容:>>>a=5上面代码没有生成任何输出,只