我问了一个关于柯里化(Currying)的问题,其中提到了闭包。 什么是闭包?它与柯里化(Currying)有何关系?
最佳答案
变量范围
当您声明局部变量时,该变量就有一个作用域。通常,局部变量仅存在于声明它们的 block 或函数内。
function() {
var a = 1;
console.log(a); // works
}
console.log(a); // fails
如果我尝试访问局部变量,大多数语言都会在当前作用域中查找它,然后向上查找父作用域,直到到达根作用域。
var a = 1;
function() {
console.log(a); // works
}
console.log(a); // works
当 block 或函数使用完毕后,不再需要其局部变量,并且通常会耗尽内存。
这就是我们通常期望事情发生的方式。
闭包是一个持久的局部变量范围
闭包是一个持久作用域,即使在代码执行移出该 block 之后,它也会保留局部变量。支持闭包的语言(例如 JavaScript、Swift 和 Ruby)将允许您保留对作用域(包括其父作用域)的引用,即使在声明这些变量的 block 已完成执行之后,前提是您保留引用到某个地方的那个 block 或函数。
作用域对象及其所有局部变量都与该函数相关联,并且只要该函数存在,它就会持续存在。
这为我们提供了函数的可移植性。我们可以预期,当我们稍后调用该函数时,首次定义该函数时在作用域内的任何变量仍然在作用域内,即使我们在完全不同的上下文中调用该函数也是如此。
例如
下面是一个非常简单的 JavaScript 示例,它说明了这一点:
outer = function() {
var a = 1;
var inner = function() {
console.log(a);
}
return inner; // this returns a function
}
var fnc = outer(); // execute outer to get inner
fnc();
这里我在函数中定义了一个函数。内部函数可以访问外部函数的所有局部变量,包括a
。变量 a
位于内部函数的范围内。
通常,当函数退出时,它的所有局部变量都会被清除。但是,如果我们返回内部函数并将其分配给变量fnc
,以便它在outer
退出后仍然存在,当inner
也被定义为持久化。变量a
已被封闭——它位于一个闭包内。
请注意,变量a
对于fnc
来说是完全私有(private)的。这是一种在函数式编程语言(例如 JavaScript)中创建私有(private)变量的方法。
您可能会猜到,当我调用 fnc()
时,它会打印 a
的值,即“1”。
在没有闭包的语言中,当函数 outer
退出时,变量 a
将被垃圾收集并丢弃。调用 fnc 会抛出错误,因为 a
不再存在。
在 JavaScript 中,变量 a
会持续存在,因为变量作用域是在函数首次声明时创建的,并且只要该函数继续存在,它就会持续存在。
a
属于outer
范围。 inner
的作用域有一个指向 outer
作用域的父指针。 fnc
是一个指向inner
的变量。只要 fnc
持续存在,a
就会持续存在。 a
在闭包内。
进一步阅读(观看)
我做了一个YouTube video查看此代码以及一些实际的使用示例。
关于functional-programming - 什么是 'Closure' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36636/