以递归方式循环遍历对象(树)

Val*_*Val 53 javascript tree jquery

有没有办法(在jQuery或JavaScript中)循环遍历每个对象,它的子孙和孙子等等?

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

例:

foo :{
  bar:'',
  child:{
    grand:{
      greatgrand: {
        //and so on
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

loop start
   if(nameof == 'child'){
     //do something
   }
   if(nameof == 'bar'){
     //do something
   }
   if(nameof =='grand'){
     //do something
   }
loop end
Run Code Online (Sandbox Code Playgroud)

And*_*y E 88

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

for (var key in foo)
{
    if (key == "child")
        // do something...
} 
Run Code Online (Sandbox Code Playgroud)

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

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

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

// 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... 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Annan:是的,这或多或少是我得到的.关键是不要这样做;-) (3认同)
  • @Val:使用对象递归来破坏浏览器会很困难.该对象需要包含对自身的引用作为属性之一:-) (2认同)
  • 尝试:`(a = {})._ = a` (2认同)
  • 我发现在为 Date 对象调用 eachRecursive() 之前我需要```// 做一些事情``` 否则这个实现会跳过它们。日期是对象,所以 eachRecursive() 被调用,但在这种情况下你真的不想递归。这是我在使用它时发现的。 (2认同)
  • object-keys 和 for-loop - 差异细节 [here](/sf/answers/3818771631/) (2认同)

Joã*_*ira 11

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

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])
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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])
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Ric*_*ick 6

如果你想找回关系树,你可以递归地使用 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));
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)