我问了一个关于curry和闭包的问题。 什么是闭包?它和咖喱有什么关系?


当前回答

凯尔的回答很好。我认为唯一需要澄清的是,闭包基本上是lambda函数创建时堆栈的快照。然后,当函数重新执行时,堆栈将恢复到执行函数之前的状态。因此,正如Kyle提到的,当lambda函数执行时,隐藏值(count)是可用的。

其他回答

变量作用域

声明局部变量时,该变量具有作用域。一般来说,局部变量只存在于声明它们的块或函数中。

function() {
  var a = 1;
  console.log(a); // works
}    
console.log(a); // fails

如果我试图访问一个局部变量,大多数语言都会在当前作用域中查找它,然后向上遍历父作用域,直到到达根作用域。

var a = 1;
function() {
  console.log(a); // works
}    
console.log(a); // works

当一个块或函数被处理完,它的局部变量就不再需要了,通常会耗尽内存。

这就是我们通常期望的事情的运作方式。

闭包是一个持久的局部变量作用域

闭包是一个持久作用域,即使在代码执行已经移出该块之后,它仍然保留局部变量。支持闭包的语言(如JavaScript、Swift和Ruby)将允许您保留对作用域(包括其父作用域)的引用,即使在声明这些变量的块已经完成执行之后,只要您在某处保留对该块或函数的引用。

作用域对象及其所有局部变量都绑定到函数,只要函数存在,它们就会存在。

这给了我们函数可移植性。我们可以预期,在函数第一次定义时在作用域中的任何变量,在稍后调用该函数时仍然在作用域中,即使我们在完全不同的上下文中调用该函数。

例如

下面是一个非常简单的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在内部函数的作用域内。

正常情况下,当一个函数退出时,它的所有局部变量都会消失。但是,如果我们返回inner函数并将其赋值给变量fnc,以便在outer退出后它仍然存在,那么定义inner时在作用域内的所有变量也将仍然存在。变量a已经被关闭了——它在一个闭包中。

注意变量a对于fnc是完全私有的。这是在函数式编程语言(如JavaScript)中创建私有变量的一种方式。

正如你可能猜到的那样,当我调用fnc()时,它会打印a的值,即“1”。

在没有闭包的语言中,当函数outer退出时,变量a将被垃圾收集并丢弃。调用fnc将抛出一个错误,因为a不再存在。

在JavaScript中,变量a持续存在,因为变量作用域是在函数第一次声明时创建的,并且只要函数继续存在,变量a就会持续存在。

A属于outer的范围。inner的作用域有一个父指针指向outer的作用域。FNC是一个指向内的变量。只要FNC存在,A就存在。A在闭包内。

进一步阅读(观看)

我制作了一个YouTube视频,介绍了这段代码的一些实际使用示例。

闭包是JavaScript中的一个特性,函数可以访问自己的作用域变量、外部函数变量和全局变量。

闭包即使在外部函数返回之后也可以访问它的外部函数作用域。这意味着闭包可以记住并访问它的外部函数的变量和参数,即使函数已经完成。

内部函数可以访问在自己的作用域、外部函数的作用域和全局作用域中定义的变量。外部函数可以访问在自己的作用域和全局作用域中定义的变量。

闭包的例子:

var globalValue = 5;

function functOuter() {
  var outerFunctionValue = 10;

  //Inner function has access to the outer function value
  //and the global variables
  function functInner() {
    var innerFunctionValue = 5;
    alert(globalValue + outerFunctionValue + innerFunctionValue);
  }
  functInner();
}
functOuter();  

输出将为20,即其内部函数自身变量、外部函数变量和全局变量值的和。

从Lua.org:

当一个函数被封装在另一个函数中编写时,它可以完全访问封装函数中的局部变量;这个特性称为词法作用域。尽管这听起来很明显,但事实并非如此。词法作用域加上第一类函数是编程语言中一个强大的概念,但很少有语言支持这个概念。

下面的示例演示了Scheme编程语言中的闭包。

首先定义一个函数,该函数定义了一个局部变量,在函数外部不可见。

; Function using a local variable
(define (function)
  (define a 1)
  (display a) ; prints 1, when calling (function)
  )
(function) ; prints 1
(display a) ; fails: a undefined

下面是同样的例子,但是现在函数使用了一个全局变量,定义在函数外部。

; Function using a global variable
(define b 2)
(define (function)
  (display b) ; prints 2, when calling (function)
  )
(function) ; prints 2
(display 2) ; prints 2

最后,这里有一个函数携带自己闭包的例子:

; Function with closure
(define (outer)
  (define c 3)
  (define (inner)
    (display c))
  inner ; outer function returns the inner function as result
  )
(define function (outer))
(function) ; prints 3

闭包 只要在另一个函数内部定义了一个函数,内部函数就可以访问声明的变量 在外层函数中。闭包最好用例子来解释。 在清单2-18中,可以看到内部函数可以访问变量variableInOuterFunction 外的范围。外部函数中的变量已被内部函数封闭(或绑定在)。因此才有了这个术语 关闭。这个概念本身很简单,也很直观。

Listing 2-18:
    function outerFunction(arg) {
     var variableInOuterFunction = arg;

     function bar() {
             console.log(variableInOuterFunction); // Access a variable from the outer scope
     }
     // Call the local function to demonstrate that it has access to arg
     bar(); 
    }
    outerFunction('hello closure!'); // logs hello closure!

来源:http://index-of.es/Varios/Basarat%20Ali%20Syed%20 (auth)。他们% 20 node.js-apress % 20 (2014) . pdf