Пройдите по всем узлам дерева объектов JSON с помощью JavaScript

Лучше — это не будет бесконечным циклом на объектах с ссылками

 //your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; // this self-referential property assignment is the only edited line // from the below original example which makes the traversal // non-terminating (ie it makes it infinite loop) oo = o; function* traverse(o, path=[]) { for (var i of Object.keys(o)) { const itemPath = path.concat(i); yield [i,o[i],itemPath]; if (o[i] !== null {amp}amp;{amp}amp; typeof(o[i])=="object") { //going one step down in the object tree!! yield* traverse(o[I], itemPath); } } } //that's all... no magic, no bloated framework for(var [key, value, path] of traverse(o)) { // do something here with each key and value console.log(key, value, path); } 

Чтобы уберечься от этого, вы можете добавить набор в замыкание, чтобы при первом вызове функции он начал формировать память об объектах, которые он видел, и не продолжал итерации, когда натолкнулся на уже увиденный объект. Приведенный ниже фрагмент кода делает это и, таким образом, обрабатывает бесконечные циклы.

 //your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; // this self-referential property assignment is the only edited line // from the below original example which makes more naive traversals // non-terminating (ie it makes it infinite loop) oo = o; function* traverse(o) { const memory = new Set(); function * innerTraversal (o, path=[]) { if(memory.has(o)) { // we've seen this object before don't iterate it return; } // add the new object to our memory. memory.add(o); for (var i of Object.keys(o)) { const itemPath = path.concat(i); yield [i,o[i],itemPath]; if (o[i] !== null {amp}amp;{amp}amp; typeof(o[i])=="object") { //going one step down in the object tree!! yield* innerTraversal(o[i], itemPath); } } } yield* innerTraversal(o); } console.log(o); //that's all... no magic, no bloated framework for(var [key, value, path] of traverse(o)) { // do something here with each key and value console.log(key, value, path); } 

Оригинальный ответ

Для более нового способа сделать это, если вы не против отказаться от IE и в основном поддерживать более современные браузеры (проверьте совместимость с таблицей es6 в kangax ). Для этого вы можете использовать генераторы es2015.

 //your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; function* traverse(o, path=[]) { for (var i in o) { const itemPath = path.concat(i); yield [i,o[i],itemPath]; if (o[i] !== null {amp}amp;{amp}amp; typeof(o[i])=="object") { //going one step down in the object tree!! yield* traverse(o[i], itemPath); } } } //that's all... no magic, no bloated framework for(var [key, value, path] of traverse(o)) { // do something here with each key and value console.log(key, value, path); } 

Если вам нужны только собственные перечислимые свойства (в основном цепочечные свойства, не относящиеся к прототипу), вы можете изменить его на итерацию, используя Object.keys и цикл for...of вместо:

 //your object var o = { foo:"bar", arr:[1,2,3], subo: { foo2:"bar2" } }; function* traverse(o,path=[]) { for (var i of Object.keys(o)) { const itemPath = path.concat(i); yield [i,o[i],itemPath]; if (o[i] !== null {amp}amp;{amp}amp; typeof(o[i])=="object") { //going one step down in the object tree!! yield* traverse(o[i],itemPath); } } } //that's all... no magic, no bloated framework for(var [key, value, path] of traverse(o)) { // do something here with each key and value console.log(key, value, path); } 

Остановка досадных обходов бесконечных объектов

Этот отредактированный ответ все еще предоставляет одно из дополнительных преимуществ моего исходного ответа, который позволяет вам использовать предоставленную функцию генератора для использования более чистого и простого итерируемого интерфейса (подумайте об использовании циклов for(var a of b) как в for(var a of b) где b является итеративным, а является элементом итерируемого).

Использование функции генератора наряду с тем, что он более простой API, также помогает в повторном использовании кода, делая его таким образом, чтобы вам не приходилось повторять логику итерации везде, где вы хотите глубоко перебрать свойства объекта, и это также дает возможность break цикла, если вы хотите остановить итерацию раньше.

Одна вещь, которую я заметил, что она не была рассмотрена и которой нет в моем первоначальном ответе, это то, что вы должны быть осторожны при обходе произвольных (то есть любого «случайного» набора) объектов, потому что объекты JavaScript могут быть самоссылочными.

Это создает возможность иметь бесконечные циклические обходы. Однако немодифицированные данные JSON не могут быть самореферентными, поэтому, если вы используете это конкретное подмножество объектов JS, вам не нужно беспокоиться о бесконечном цикле обходов, и вы можете обратиться к моему исходному ответу или другим ответам.

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector