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