繁体   English   中英

递归循环 object(树)

[英]looping through an object (tree) recursively

有没有办法(在 jQuery 或 JavaScript 中)遍历每个 object 及其子孙等等?

如果是这样...我也可以读出他们的名字吗?

例子:

foo :{
  bar:'',
  child:{
    grand:{
      greatgrand: {
        //and so on
      }
    }
  }
}

所以循环应该做这样的事情......

loop start
   if(nameof == 'child'){
     //do something
   }
   if(nameof == 'bar'){
     //do something
   }
   if(nameof =='grand'){
     //do something
   }
loop end

您正在寻找 for for...in循环:

for (var key in foo)
{
    if (key == "child")
        // do something...
} 

请注意, for...in循环将遍历任何可枚举属性,包括添加到对象原型中的属性。 为了避免对这些属性进行操作,您可以使用hasOwnProperty方法来检查该属性是否仅属于该对象:

for (var key in foo)
{
    if (!foo.hasOwnProperty(key))
        continue;       // skip this property
    if (key == "child")
        // do something...
}

以递归方式执行循环可以像编写递归函数一样简单:

// This function handles arrays and objects
function eachRecursive(obj)
{
    for (var k in obj)
    {
        if (typeof obj[k] == "object" && obj[k] !== null)
            eachRecursive(obj[k]);
        else
            // do something... 
    }
}

你可以有一个递归函数,其中内置了一个解析函数。

function parseObjectProperties (obj, parse) {
  for (var k in obj) {
    if (typeof obj[k] === 'object' && obj[k] !== null) {
      parseObjectProperties(obj[k], parse)
    } else if (obj.hasOwnProperty(k)) {
      parse(k, obj[k])
    }
  }
}

我使用 OP 的foo对象,这里是它是如何工作的

 var foo = { bar:'a', child:{ b: 'b', grand:{ greatgrand: { c:'c' } } } } // use this recursive function with a parse funciton function parseObjectProperties (obj, parse) { for (var k in obj) { if (typeof obj[k] === 'object' && obj[k] !== null) { parseObjectProperties(obj[k], parse) } else if (obj.hasOwnProperty(k)) { parse(k, obj[k]) } } } //*** // then apply to the property the task you want, in this case just console parseObjectProperties(foo, function(k, prop) { console.log(k + ': ' + prop) })

如果你想找回关系树,你可以递归地使用 Object.keys。

 function paths(item) { function iter(r, p) { var keys = Object.keys(r); if (keys.length) { return keys.forEach(x => iter(r[x], p.concat(x))); } result.push(p); } var result = []; iter(item, []); return result; } var data = { foo: { bar: '', child: { grand: { greatgrand: {} } } } }; console.log(paths(data));

这可以扩展为在对象结构中搜索与函数匹配的值:

 function objectSearch(rootItem, matcher) { const visited = []; const paths = []; function iterate(item, path) { if (visited.includes(item)) { return; } visited.push(item); if (typeof item === "object" && item !== null) { var keys = Object.keys(item); if (keys.length) { return keys.forEach(key => iterate(item[key], path.concat(key))); } } if (matcher(item)) { paths.push(path); } } iterate(rootItem, []); return paths; } function searchForNaNs(rootItem) { return objectSearch(rootItem, (v) => Object.is(NaN, v)); } var banana = { foo: { bar: "", child: { grand: { greatgrand: {}, nanan: "NaN", nan: NaN, }, }, }, }; console.log("There's a NaN at", searchForNaNs(banana)[0].join("."), "in this object:", banana);

考虑使用object-scan 一旦你把头环绕在它周围,它对于数据处理来说是强大的。

一件很棒的事情是这些项目以“删除安全”的顺序遍历。 所以如果你删除一个,它不会搞乱循环。 而且您可以访问许多其他属性,例如父母等。

 // const objectScan = require('object-scan'); const obj = { foo: { bar: '', child: { grand: { greatgrand: { /* and so on */ } } } } }; objectScan(['**'], { filterFn: ({ property }) => { console.log(property); } })(obj); // => greatgrand // => grand // => child // => bar // => foo
 .as-console-wrapper {max-height: 100% !important; top: 0}
 <script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是对象扫描的作者

我建议使用sindresorhusmap-objfilter-obj实用程序...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM