Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
试图理解javascript中for循环中的递归_Javascript_For Loop_Recursion - Fatal编程技术网

试图理解javascript中for循环中的递归

试图理解javascript中for循环中的递归,javascript,for-loop,recursion,Javascript,For Loop,Recursion,我一直盯着这个问题的答案,甚至在每次迭代中写下变量等等。我只是不明白这个过程。当我插入控制台日志时,我看到permute被称为input.length—在它到达这一行input.splice(I,0,ch)之前被调用了1次;当我完全迷路的时候,很难表达这个问题,但我想有些奇怪的是:每次调用permute时,它都是该函数的一个新实例,具有自己的闭包,对吗?因此,函数中的变量更改不会影响其他调用中的变量?函数是否每次调用时都返回permArr?我想这不一定会影响第一次呼叫的返回?(我的直觉告诉我,第

我一直盯着这个问题的答案,甚至在每次迭代中写下变量等等。我只是不明白这个过程。当我插入控制台日志时,我看到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
};