Javascript 删除属性映射中的间接循环对象引用
我有这个任务。我有一个对象,它可以包含任何内容作为属性值-数组、对象、基元值本身,并且可以具有任意嵌套属性(不关心符号) 我需要像这样建立一个对象属性的映射Javascript 删除属性映射中的间接循环对象引用,javascript,ecmascript-6,Javascript,Ecmascript 6,我有这个任务。我有一个对象,它可以包含任何内容作为属性值-数组、对象、基元值本身,并且可以具有任意嵌套属性(不关心符号) 我需要像这样建立一个对象属性的映射 const obj = { p1: 'this', p2: ['that'], p3: { q: 'other' } } 变成=> ["p1", "this"] ["p2/0", "that"] ["p3/q", "other"] 我已经创建了可以处理这些东西的代码,任意嵌套、直接循环引用和某种程度上的间接循环引
const obj = {
p1: 'this',
p2: ['that'],
p3: { q: 'other' }
}
变成=>
["p1", "this"]
["p2/0", "that"]
["p3/q", "other"]
我已经创建了可以处理这些东西的代码,任意嵌套、直接循环引用和某种程度上的间接循环引用(这部分需要一些调整)
运行时,它会处理间接循环引用,因为它不会崩溃,但日志比我希望的要多
例如,在这种特殊情况下(输出的一部分)
有人知道如何/在哪里更改上面代码中的任何内容来实现这一点吗?我想你是想测试
如果(!visted.has(o[key]),
而不是如果(!visted.has(o))
。这同样适用于Visited.set——您应该使用正在查看的新对象,而不是旧对象
总之,您甚至不需要使用Map
来存储路径,Set
就足以收集访问过的对象。通过将typecheck和visted
check移动到函数前面,作为递归的基本情况,您可以省去很多麻烦:
function traverse(val, path = '', result = new Map, visited = new WeakSet) {
if (typeof val != 'object' || val == null) {
result.set(path, val);
} else /* it's an object */ if (!visited.has(val)) {
visited.add(val);
for (const key in val) {
traverse(val[key], path + '/' + key, result, visited);
}
}
return result;
}
如果一个对象结构对同一对象有多个引用(不一定是圆形的),并且希望输出到该对象的最短路径,则需要使用a而不是当前的深度优先路径。如果值是唯一的(或至少不重复),您不能简单地在现有结果中搜索该值,并且没有添加新的[key,value]数组吗?@CertainPerformance好也许我可以测试结果,我只是不知道直接测试有多大帮助,因为从上面的示例可以看出,并将结果切片以测试最后一部分,例如
label:myObj
,是否也不可行,因为另一个对象可能会产生相同的后缀,删除该后缀将是一个错误(通常,值不是唯一的,如果由不同的对象生成,则可以重复)。很遗憾,我不知道如何从函数的输出中重建所需的输出,因为它也包含重复的信息。哎呀,我把我的论点顺序弄乱了。现在它没有多次输出任何内容。
// this is ok
["label", "myObj"]
// this should not be included as the information is already there
["metaInfo/other/label", "myObj"]
function traverse(val, path = '', result = new Map, visited = new WeakSet) {
if (typeof val != 'object' || val == null) {
result.set(path, val);
} else /* it's an object */ if (!visited.has(val)) {
visited.add(val);
for (const key in val) {
traverse(val[key], path + '/' + key, result, visited);
}
}
return result;
}