我一直在更具体地阅读closure concept of programming,特别是与Javascript有关。我还没有完全理解它与我多年来写的Javascript代码有什么不同。我也理解递归的概念,但我想知道,闭包和递归是如何相似的?我是否正确理解递归本身就是一种闭包?
关闭:
function init() {
var name = "Stack Overflow";
function displayName() {
alert(name);
}
displayName();
}
init();
递归:
function factorial(num) {
if(num < 0)
return -1;
else if(num == 0)
return 1;
else
return (num * factorial(num - 1));
}
alert(factorial(8));
我认为我开始明白闭包只不过是在函数中有一个函数,内部函数可以通过作用域访问外部函数。可能会有递归闭包吗?我的意思是,虽然我的递归示例也不是关闭的例子,但它至少会发生吗?我试图理解递归和闭包是如何相似,不同,或者它们是否甚至可以被所有人比较。有没有例子可以描述这个?
答案 0 :(得分:7)
闭包只是一个“关闭”环境(它的正文)的函数或过程。在您的代码中,init
,displayName
和factorial
都是封闭式的。当您想要创建闭包时,可以使用JavaScript function
关键字(或者现在我们在ES6中有=>
箭头函数)。
递归是程序重复的效果
我一直在读一本新书,它谈到了一些相关的话题。我想我会在这里分享一些笔记,以防你感兴趣。
这是计算阶乘的递归函数。它与你的一样,但是以一种非常不同的方式。我们来看看吧!
function factorial(x) {
if (x < 0) throw Error("Cannot calculate factorial of a negative number");
function iter(i, fact) {
return i === 0 ? fact : iter(i-1, i*fact);
}
return iter(x, 1);
}
factorial(6); // 720
将它与您在上面定义的 ^。^ 进行比较。请注意,即使它是递归的,它也不会再次调用自身(factorial
)。这使用了一个消耗线性空间和时间的线性迭代过程。对函数的评估看起来像这样
factorial(6);
iter(6, 1);
iter(5, 6*1);
iter(4, 5*6);
iter(3, 4*30);
iter(2, 3*120);
iter(1, 2*360);
iter(0, 1*720);
// => 720
将其与您的功能过程进行比较。这是你的看法
factorial(6);
(6 * factorial(5));
(6 * (5 * factorial(4)));
(6 * (5 * (4 * factorial(3))));
(6 * (5 * (4 * (3 * factorial(2)))));
(6 * (5 * (4 * (3 * (2 * factorial(1))))));
(6 * (5 * (4 * (3 * (2 * 1)))));
// => 720
请注意,随着n
的增加,n!
会添加另一个堆栈调用。这是一个线性递归过程。对于较大的n
值,此方法使用更多空间来计算相同的结果。
答案 1 :(得分:1)
我之前尝试过关于闭包的文章(尽管没有提到递归):
http://hangar.runway7.net/javascript/guide
但是关于递归,我会说在递归发生时闭包可以进入,但它们不一定相关。我实际上建议你不要在递归中使用闭包,因为这会导致意外的错误。递归通常依赖于每个函数调用执行时只有明确传递给它的参数的知识,并且闭包违反了这个原则。
实际上,闭包是一种在定义函数时在函数之间共享信息的方法,尤其是当您知道它们将在未知的上下文中执行时。
另一方面,递归是一个函数的执行过程,该函数的结构使得它通过重复调用自身来完成它的工作。通过谷歌搜索它们可以更好地学习这两个概念,但只知道它们通常不相关。