Есть ли способ обойти возможно самодостаточный объект в JavaScript? - PullRequest
3 голосов
/ 08 апреля 2019

Я хочу убрать объект в Javascript в поисках определенной строки. К сожалению, этот объект построен таким образом, что было бы невозможно просто использовать исходные тексты и Ctrl-F для этой строки, а также он построен таким образом, что рекурсивные функции, пытающиеся спускаться по нему, рискуют оказаться в ловушке внутри него. навсегда.

По сути, этот объект содержит себя. Не только один раз, но и в очень многих областях. Я не могу просто сказать «исключить эти ключи», так как объект запутан, и поэтому мы будем здесь весь день, перечисляя ключи, и как только мы закончим, мы бы не посмотрели все данные.
Кроме того, мне нужно иметь возможность спускаться по __proto__ и prototype, поскольку там также скрыты полезные строки. (Но только для функций и объектов.)

Хотя я бы предпочел что-то вроде findStuff(object, /string/ig), это может быть сложно, поэтому любая функция, которая просто имеет области, четко помеченные, что поток управления падает до того момента, когда обнаружены определенные объекты (функция, строка и т. Д.)

Спасибо, и извините за такую ​​боль в заднем вопросе.


Edit: в случае, если это помогает, я пытаюсь пройти скомпилированный объект времени выполнения Construct2. Я не собираюсь публиковать здесь полную информацию, так как она не помещается ни в одну вставку, независимо от того, насколько она простительна, а также я не хочу случайно публиковать ресурсы, на которые у меня нет разрешения. (Не волнуйтесь, я не пытаюсь пиратствовать сам, я просто пытаюсь выяснить некоторые функции, ориентированные на пользователя)

Ответы [ 3 ]

2 голосов
/ 08 апреля 2019

Каждый раз, когда вы проходите потенциально циклический объект, сохраняете памятку о уже пройденных объектах и ​​ломаетесь, если вы видели текущий объект ранее, - это стандартная техника.Для этого вы можете использовать Set.

2 голосов
/ 08 апреля 2019

Ведите список объектов, в которые вы рекурсировали, а затем сверяйте каждый новый объект с этим списком.

const data = {
  foo: {
    bar: 1
  },
  one: 1,
  jaz: {
    hello: {
      x: 1
    }
  }
};

data.bar = data.foo;
data.foo.foo = data.foo;
data.jaz.hello.foo = data;

function search_for_1() {
  const seen = [];
  search(data);

  function search(object) {
    Object.values(object).forEach(value => {
      if (typeof value === "object") {
        if (seen.includes(value)) {
          console.log("Seen this already");
        } else {
          seen.push(value);
          search(value);
        }
      } else {
        if (value === 1) {
          console.log("Found 1");
        }
      }
    });
  }
}

search_for_1();
2 голосов
/ 08 апреля 2019

Вы можете использовать WeakSet для отслеживания объектов, которые уже были пройдены:

 function traverseOnce(obj, cb) {
   const visited = new WeakSet();
   (function traverse(obj) {
     for(const [key, value] of Object.entries(obj)) {
       if(typeof value === "object" && value !== null) {
          if(visited.has(value)) continue;
          visited.add(value);
          cb(value);
          traverse(value);
       }
      }
   })(obj);
 }

Через WeakSet вы получаете O (1) время поиска, а также уверены, что оно никогда не просочится.

Используется как:

 const nested = { other: { a: 1 } };
 nested.self = nested;

 traverseOnce(nested, console.log);
 // nested: { other, self }
 // other: { a: 1 }

Вы также можете использовать Символ для обозначения пройденных объектов, для этого замените new WeakSet() на Symbol(), visited.has(value) на value[visited] и visuted.add(value) на value[visited] = true;

...