闭包是一个外部函数O,它在其体内有一个变量x和一个内部函数F.F必须访问x。 O必须返回F,即F本身(或其指针),而不是F的返回值。这样,因为F可以从O外部的代码调用,而F需要执行x,所以x必须保留在范围之后O退出。
在javascript中我们可以定义函数内的函数,因此它是直截了当的。在C#中,我们必须使用匿名方法或匿名委托来与内部函数具有相同的行为。
闭包的本质是在函数退出后保留函数的局部变量的值,以便下次调用函数时,先前的值已经存在。上面提到的语法和技术是完成闭包的方法。
无论如何,使用任何语言(汇编语言除外)都可以在不使用内部函数或委托的情况下获得闭包的本质。 OOP中的课程中的课程字段具有相同的效果,但我正在寻找除此之外的方法。
答案 0 :(得分:1)
根据定义,闭包关闭其词法范围中的变量。如果它不能通过局部变量“内在”其他东西,那将完全没用。因此,闭包必须能够在某个函数内部。
然而,一个复杂性是某些语言中的闭包与匿名函数密切相关。 (匿名函数通常必须是闭包;闭包不一定是匿名函数,但在某些语言中,唯一的闭包是匿名函数。)匿名函数的语法可能与常规(命名)函数的语法不同(特别是在语言中)函数和变量的单独命名空间;命名函数将在函数命名空间中,但匿名函数将是数据)。在某些语言中,没有“内部”命名函数。
例如,在PHP中,所有命名函数都在全局范围内。将命名函数定义放在另一个函数定义中(违反直觉)定义了外部函数运行时全局作用域中的内部函数(外部代码可以看到它)(好像它在外部作用域中声明,但是被延迟)。但是,PHP 5.3+也有匿名函数,它们是闭包;人们通常将匿名函数称为“闭包”,因为它们是该语言中唯一的闭包。
另一个例子是Ruby。 def
语法定义了一种方法。在另一个方法中定义一个方法(违反直觉)仍然将该方法定义为对其他方法可见。 Ruby也使用lambda
,proc
或Proc.new
语法来创建闭包的匿名函数,但这些函数在语法上是不同的。
答案 1 :(得分:0)
我不会将它们称为闭包,但保留状态的局部变量的概念是在VB中使用Static
局部变量。
Sub Example()
Dim normalVar As Integer
Static staticVar As Integer
normalVar += 1
staticVar += 1
Console.WriteLine("{0} {1}", normalVar, staticVar)
End Sub
(这是VB.NET但Static
在VB3或更早版本中。)
这将输出
1 1
1 2
1 3
如果被叫三次。