我问了一个关于curry和闭包的问题。 什么是闭包?它和咖喱有什么关系?
当前回答
从Lua.org:
当一个函数被封装在另一个函数中编写时,它可以完全访问封装函数中的局部变量;这个特性称为词法作用域。尽管这听起来很明显,但事实并非如此。词法作用域加上第一类函数是编程语言中一个强大的概念,但很少有语言支持这个概念。
其他回答
不包含自由变量的函数称为纯函数。
包含一个或多个自由变量的函数称为闭包。
var pure = function pure(x){
return x
// only own environment is used
}
var foo = "bar"
var closure = function closure(){
return foo
// foo is a free variable from the outer environment
}
src: https://leanpub.com/javascriptallongesix/read # leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure
闭包是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,即其内部函数自身变量、外部函数变量和全局变量值的和。
curry:它允许你通过只传入函数参数的子集来部分求值。考虑一下:
function multiply (x, y) {
return x * y;
}
const double = multiply.bind(null, 2);
const eight = double(4);
eight == 8;
闭包:闭包只不过是访问函数作用域之外的变量。重要的是要记住,函数中的函数或嵌套函数不是闭包。当需要访问函数作用域外的变量时,总是使用闭包。
function apple(x){
function google(y,z) {
console.log(x*y);
}
google(7,2);
}
apple(3);
// the answer here will be 21
凯尔的回答很好。我认为唯一需要澄清的是,闭包基本上是lambda函数创建时堆栈的快照。然后,当函数重新执行时,堆栈将恢复到执行函数之前的状态。因此,正如Kyle提到的,当lambda函数执行时,隐藏值(count)是可用的。
我将给出一个例子(JavaScript):
function makeCounter () {
var count = 0;
return function () {
count += 1;
return count;
}
}
var x = makeCounter();
x(); returns 1
x(); returns 2
...etc...
这个makeCounter函数的作用是,它返回一个函数,我们称之为x,每次调用它都会加1。由于我们没有为x提供任何参数,它必须以某种方式记住计数。它知道根据所谓的词法作用域在哪里找到它——它必须查找定义值的位置才能找到值。这个“隐藏”值就是所谓的闭包。
下面还是我用咖喱的例子:
function add (a) {
return function (b) {
return a + b;
}
}
var add3 = add(3);
add3(4); returns 7
您可以看到,当您使用参数a(即3)调用add时,该值包含在我们定义为add3的返回函数的闭包中。这样,当我们调用add3时,它知道在哪里找到a值来执行加法。