Javascript 递归函数如何单步遍历数组元素或对象属性

Javascript 递归函数如何单步遍历数组元素或对象属性,javascript,object,recursion,Javascript,Object,Recursion,如果这是一个愚蠢的问题,我道歉。我真的无法通过谷歌找到任何关于这个主题的资源。我不明白如何在递归函数中单步遍历对象的属性数组,因为根据定义,递归将循环遍历自身。我知道如何在递归中不使用for循环迭代数组。我不明白的是如何循环对象进行递归。这只是我编造的一些代码,以证明我缺乏理解 var input1 = [1, 2, 3, 4, 5]; var input2 = {1: 'a', 2: 'b', 3: 'c'}; //for arrays var arrayRecursion = functi

如果这是一个愚蠢的问题,我道歉。我真的无法通过谷歌找到任何关于这个主题的资源。我不明白如何在递归函数中单步遍历对象的属性数组,因为根据定义,递归将循环遍历自身。我知道如何在递归中不使用for循环迭代数组。我不明白的是如何循环对象进行递归。这只是我编造的一些代码,以证明我缺乏理解

var input1 = [1, 2, 3, 4, 5];
var input2 = {1: 'a', 2: 'b', 3: 'c'};

//for arrays
var arrayRecursion = function(someArray) {
  var result = [];

  //base case
  if (someArray.length === 0) {
    return result;
  } else {
    result.push(someArray.slice(0, 1));
    return result.concat(arrayRecursion(someArray.slice(1)));
  }
}

//for objects trying to copy input into results
var objectRecursion = function(someObject) {
  var result = {};

  for (var value in someObject) {
  //base case
  if (typeof(someObject[key]) !== 'object') {
      return result;
  }
  //recursion
  }
}

我的主要问题是我的对象递归。如果我为一个对象建立了for-in循环。它是如何迭代的?我没有填写递归,因为我不知道如何处理这个问题。如果我调用对象的递归,它会移到对象的下一个属性吗?如果是,怎么做?难道你不会从一开始就重新开始for-in循环吗?我想我的逻辑是,for循环并不是从每次调用的递归中继续的,因为它执行从第一个属性开始循环的函数。

for

一旦对对象的值进行了引用,请检查它是否为对象。如果它是一个对象,则调用递归
objectRecursion
,并将结果分配给同一属性的
result
对象。(此时不要返回
,因为这样会终止函数)

请注意,
typeof
是一个关键字,而不是一个函数-不要在它后面加括号

一个相关的问题是
null
typeof
也是
object
,因此您还必须与之进行比较

var input2={1:a',2:b',3:c',foo:{prop:2};
const objectRecursion=(someObject)=>{
const result={};
for(Object.entries(someObject))的常量[key,value]{
结果[键]=值的类型=='object'&&value!==null
?对象递归(值)
:价值;
}
返回结果;
};

log(objectRecursion(input2))我对对象使用递归的经验主要是通过嵌套对象进行递归,而不是通过同一对象上的键集和值集进行递归。我认为这是因为递归作为一种模式自然地适合于分形的事物——也就是说,在递归深度的每个层次上操作的数据在结构上是相似的

树木就是一个很好的例子。假设我有一个具有以下结构的节点对象树:

4 - 8 - 9
|   |
2   5 - 7
|
1
作为JS对象,它可能如下所示

{
  val: 4,
  left: {
    val: 2,
    left: {
      val: 1
    }
  },
  right: {
    val: 8,
    left: {
      val: 5,
      right: {
        val: 7
      }
    },
    right: {
      val: 9
    }
  }
}
注意,如果我从根节点看表示左或右节点的对象,它的结构与其父节点相同?它们实际上是各自的树,但结合成一棵更大的树(这就是我所说的分形)

如果您想在这棵树中找到最大的值,可以使用递归遍历分支

const getLargest = function (node) {
  return Math.max(node.val, getLargest(node.left), getLargest(node.right));
};
也就是说,在对象中对越来越小的键值对集合使用递归是完全可能的。它可能看起来像这样:

const exampleObject = {
  a: 1,
  b: 2,
  c: 3
};

const recurse = function(obj) {
  const keys = Object.keys(obj);
  const firstKey = keys[0];
  console.log(obj[firstKey]); // Or whatever; do a thing with the first key-value pair.

  const smallerObj = Object.assign({}, obj); // Create a clone of the original; not necessary, but probably a good idea.
  delete smallerObj[firstKey]; // Remove the key that we've just used.
  recurse(smallerObj);
};

这在JS中有点不自然,但仍然完全可行。JavaScript对象键没有排序,但是如果您想按特定顺序运行键,可以将排序添加到
const keys=object.keys(obj)

这应该使用apply递归工作


不过,数组示例并没有真正递归;e、 g.
[1,2,3,4]
不会以
[1,2,3,4]
的结果结束欢迎来到StackOverflow,只要你以深思熟虑的方式(你做到了)提出这些问题,就不会有不好的问题@杰克在一定的表现上说得很好。谢谢你的回复。它仍然没有在我的脑海中点击。对第一个属性说:
1:'a'
。如果我理解正确,代码会说
If result[1]=typeof'object'&&&!=空
然后
对象递归('a')
else
'a'
。很抱歉,我没有经常使用
运算符,希望我能正确理解。我不明白您是如何将这些值复制到结果中的,以及它是如何移动到下一个属性的。
objectRecursion('a')
如何让您查看
2:'b'
?您需要分离键和值,这就是Object.entries(someItem)的
const[key,value]所做的。然后,它通过检查值的类型来确定如何转换值,最后将结果分配给
result
对象的同一个键。
是条件运算符,它允许在有条件地构造表达式时使用更简洁的语法-在这种情况下,如果
/
,它通常比
更简洁、更合适。例如
obj[key]=cond?val1:val2
相当于
if(cond){obj[key]=val1;}else{obj[key]=val2;}
谢谢。我花了很长时间才意识到
if
条件是为嵌套对象编写的。掌纹
var o = {1: 'a', 2: 'b', 3: 'c', foo: { prop: 2, prop2: [3, 4, 5, { nested: 'nested' }] }};


function process(key,value) {
    console.log(key + " : "+value);
}

function traverse(o,func) {
    for (var i in o) {
        func.apply(this,[i,o[i]]);  
        if (o[i] !== null && typeof(o[i])=="object") {
             traverse(o[i],func);
        }
    }
}

traverse(o,process);