试图理解javascript中for循环中的递归
我一直盯着这个问题的答案,甚至在每次迭代中写下变量等等。我只是不明白这个过程。当我插入控制台日志时,我看到permute被称为input.length—在它到达这一行input.splice(I,0,ch)之前被调用了1次;当我完全迷路的时候,很难表达这个问题,但我想有些奇怪的是:每次调用permute时,它都是该函数的一个新实例,具有自己的闭包,对吗?因此,函数中的变量更改不会影响其他调用中的变量?函数是否每次调用时都返回permArr?我想这不一定会影响第一次呼叫的返回?(我的直觉告诉我,第一次返回时,函数停止运行) 谢谢你的洞察力试图理解javascript中for循环中的递归,javascript,for-loop,recursion,Javascript,For Loop,Recursion,我一直盯着这个问题的答案,甚至在每次迭代中写下变量等等。我只是不明白这个过程。当我插入控制台日志时,我看到permute被称为input.length—在它到达这一行input.splice(I,0,ch)之前被调用了1次;当我完全迷路的时候,很难表达这个问题,但我想有些奇怪的是:每次调用permute时,它都是该函数的一个新实例,具有自己的闭包,对吗?因此,函数中的变量更改不会影响其他调用中的变量?函数是否每次调用时都返回permArr?我想这不一定会影响第一次呼叫的返回?(我的直觉告诉我,第
var permArr=[],
usedChars=[];
函数置换(输入){
varⅠ,ch;
对于(i=0;i
代码有点难理解,因为它是循环和递归的混合体。它使用一个全局变量(usedChars
),该变量在每次调用期间都会更改和恢复
“每次调用permute时,它都是该函数的一个新实例
有了它自己的闭包,对吗?因此变量的变化是
函数中的变量不会影响其他调用中的变量?”
好的,是和否。每个函数调用都有自己的作用域,但由于没有需要捕获的变量,因此没有闭包。局部变量i
和ch
以及参数input
都是作用域的局部变量,因此每个调用都有自己的变量集。任何其他变量都是全局变量,因此它们在所有调用之间共享
变量usedChars
在代码中更改,当函数执行递归调用时,该更改对代码可见,然后在下一次迭代中将该变量更改回上一个状态。当函数存在时,变量具有输入函数时的值
“函数是否每次调用时都返回permArr?”
是的,但是当函数调用自身时,返回值被忽略。只有当数组从最外层调用返回时,才会使用它。我来试一试 概述 您从两个具有全局作用域的数组开始:
permArray
最终将保存所有置换数组,usedChars
是一个工作数组,用于通过所有递归调用构建每个置换数组。需要注意的是,在创建的每个函数的作用域中,只有这两个变量是可访问的。所有其他变量都有其自身函数调用的局部作用域
然后是递归函数,它接受一个数组作为输入,并返回一个包含输入数组所有可能排列的数组数组。现在,在这个特定的函数中,递归调用在一个循环中。这很有趣,因为终止条件实际上比基本递归函数更复杂——当您传入一个空的input
数组时,递归调用终止,for循环跳过下一个递归调用
总结
考虑一个四元素数组输入。在高层,函数将循环这个数组的四个元素,取出每个元素,并计算三个元素组成的较小数组的排列。对于所有这三个元素的排列,它将把拉出的原始元素附加到开头,并将这四个元素数组中的每一个添加到permArray
但是,为了找到较小的三元素数组的排列,我们拉出每个元素,计算两个元素组成的较小数组的排列,将拉出的元素添加到每个排列的开头,并返回递归调用堆栈中这三个元素数组中的每一个,这样原始的第四个元素就可以添加到开头,并作为一个置换计数
但是,为了找到较小的两个元素数组的排列,我们拉出每个元素,计算一个元素的较小数组的排列,将拉出的元素添加到每个排列的开头,并将这两个元素数组中的每一个返回递归调用堆栈,这样原始的第三个元素就可以添加到该排列的开头并返回堆栈
但是,为了找到较小的单元素数组的排列,我们取出元素并计算空数组的排列,它只是返回,而我们反过来只返回堆栈中的一个元素,这样原始的第二个元素就可以添加到该排列的开头并返回堆栈
细节
让我们注意一下此函数中的一些步骤:
var permArr = [],
usedChars = [];
function permute(input) {
var i, ch;
for (i = 0; i < input.length; i++) { // loop over all elements
ch = input.splice(i, 1)[0]; //1. pull out each element in turn
usedChars.push(ch); // push this element
if (input.length == 0) { //2. if input is empty, we pushed every element
permArr.push(usedChars.slice()); // so add it as a permutation
}
permute(input); //3. compute the permutation of the smaller array
input.splice(i, 0, ch); //4. add the original element to the beginning
// making input the same size as when we started
// but in a different order
usedChars.pop(); //5. remove the element we pushed
}
return permArr //return, but this only matters in the last call
};
var permArr=[],
usedChars=[];
函数置换(输入){
varⅠ,ch;
对于(i=0;ivar permArr = [],
usedChars = [];
function permute(input) {
var i, ch;
for (i = 0; i < input.length; i++) { // loop over all elements
ch = input.splice(i, 1)[0]; //1. pull out each element in turn
usedChars.push(ch); // push this element
if (input.length == 0) { //2. if input is empty, we pushed every element
permArr.push(usedChars.slice()); // so add it as a permutation
}
permute(input); //3. compute the permutation of the smaller array
input.splice(i, 0, ch); //4. add the original element to the beginning
// making input the same size as when we started
// but in a different order
usedChars.pop(); //5. remove the element we pushed
}
return permArr //return, but this only matters in the last call
};