我想在Javascript中降级一个对象,以查找特定的字符串。不幸的是,该对象的构建方式使得不可能简单地对该字符串使用源代码和Ctrl-F,并且它的构建方式也使得递归函数试图对其进行降级可能会陷入其内部。永远。
基本上,此对象包含自身。不仅一次,而且在很多地区。我不能简单地说“排除这些键”,因为对象被混淆了,因此我们会整天在这里列出键,一旦完成,我们就不会查看所有数据。
同样,我还需要能够下降__proto__
和prototype
,因为有用的字符串也隐藏在其中。 (但仅适用于函数和对象。)
虽然我更喜欢findStuff(object, /string/ig)
这样的东西,但可能很难,所以任何简单地具有明确标记区域的函数,一旦找到特定的对象(函数,字符串等),就明确地将控制流归入)
谢谢您,对接问题中的如此痛苦。
编辑:如果有帮助,我尝试遍历已编译的Construct2运行时对象。我不会在此处发布完整内容,因为无论多么宽容,它都无法放入任何pastebin中,而且我也不想偶然发布我没有提供权限的资源。 (不过,请放心,我不是要自己盗版,我只是想弄清楚一些面向用户的功能)
答案 0 :(得分:2)
您可以使用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)
替换为{{1 }}
答案 1 :(得分:2)
每次遍历潜在的循环对象时,保留已遍历的对象的备忘并在以前看过当前对象的情况下中断是一种标准技术。您可以使用Set
来这样做。
答案 2 :(得分:2)
保留递归对象的列表,然后对照该列表检查每个新对象。
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();
答案 3 :(得分:0)
不要重新发明轮子。有很多这类库。
我们使用object-scan进行所有数据处理。一旦将头缠绕在它上,它就会非常强大。这是如何解决您的问题
const objectScan = require('object-scan');
const traverse = (data) => objectScan(['**'], {
filterFn: ({ key, value, parent }) => {
// do something here
},
breakFn: ({ isCircular }) => isCircular === true
})(data);
const circular = {
name: 'Max',
age: 5,
sex: undefined,
details: {
color: 'black',
breed: undefined
}
};
circular.sex = circular;
circular.details.breed = circular;
console.log(traverse(circular));
// => [ [ 'details', 'breed' ],
// [ 'details', 'color' ],
// [ 'details' ],
// [ 'sex' ],
// [ 'age' ],
// [ 'name' ] ]