functional-programming - 什么是 'Closure' ?

标签 functional-programming computer-science terminology glossary

我问了一个关于柯里化(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/

相关文章:

algorithm - 什么是循环不变量?

过程或函数式编程语言中的单元测试

functional-programming - 简单的结构演算中的构造函数是不相交和单射的吗?

algorithm - 确定浮点平方根

terminology - "refinement"的逆概念是什么

functional-programming - 依赖注入(inject)和控制反转 - 术语

javascript - 为什么延迟评估可以将不纯函数转换为纯函数?

javascript - JavaScript 是否有像 "range()"这样的方法在提供的范围内生成范围?

java - 创建简单递归函数的递归方程

python - 在每个可能的组合中调用函数