[英]How to best compare two multi-level objects in JavaScript in order to find differences?
So I have a JavaScript function that gets an object and has a precreated object. 所以我有一个JavaScript函数,它获取一个对象并具有一个预先创建的对象。 The goal is that the function adds all missing properties of the passed object to the precreated one.
目标是该函数将传递的对象的所有缺失属性添加到预先创建的对象中。
When just comparing one level, this is easy. 只比较一个级别,这很容易。 For example in order to achieve this:
例如,为了实现这一点:
Precreated: {hello: "world"}
Passed: {hello: "there", colour: "green"}
Result: {hello: "world", colour: "green"}
You just look over each key of the passed object, look if that key already exists in the precreated one, and if not, add it with the respective value. 您只需查看传递对象的每个键,查看该键是否已存在于预先创建的键中,如果不存在,则使用相应的值添加它。
However, if you want to do this with multiple levels it kinda gets weird. 但是,如果你想用多个级别来做这件事有点奇怪。 For example, I want this to work:
例如,我想要这个工作:
Precreated: {hello: {there: true}}
Passed: {hello: {world: true}}
Result: {hello: {there: true, world: true}}
My idea was that I would just loop over the passed object, and if I find an object inside, call the function again with that object, and so on until all children were processed by the function. 我的想法是,我只是遍历传递的对象,如果我在里面找到一个对象,再用该对象调用该函数,依此类推,直到所有子节点都被该函数处理。
When you do that, however, you would have to compare the children of both objects dynamically. 但是,当您这样做时,您必须动态地比较两个对象的子项。 Say, I know in the programme how many levels deep it is, what the key is called and so on, how do I programmatically access it?
说,我在程序中知道它的深度是多少,调用了什么键等等,我如何以编程方式访问它?
I'm asking because I can't hardcode something like if (result[key1][key2][key3]...
, and something like if (result[keys.join(..)]...
isn't possible as well I think. 我问,因为我不能硬编码像
if (result[key1][key2][key3]...
,和if (result[keys.join(..)]...
是不可能的我想也是。
So how do I programmatically access a property of an object which is multiple levels deep, not knowing how deep at the time of writing the code? 那么我如何以编程方式访问多层深度的对象的属性,而不知道编写代码时有多深?
This existing answer to a post mentioned by @4castle should be exactly what you want: https://stackoverflow.com/a/34749873/1406083 这个@ 4castle提到的帖子的现有答案应该是你想要的: https ://stackoverflow.com/a/34749873/1406083
My idea was that I would just loop over the passed object, and if I find an object inside, call the function again with that object, and so on until all children were processed by the function.
我的想法是,我只是遍历传递的对象,如果我在里面找到一个对象,再用该对象调用该函数,依此类推,直到所有子节点都被该函数处理。
You've already worked out that you want to use recursion, which is great. 你已经知道你想要使用递归,这很棒。 JavaScript allows you to reflect on the keys of an object with a
for ... in
loop. JavaScript允许您使用
for ... in
循环来反映对象的键。 You just need to make sure that the object you want to copy is indeed an object and not just a value. 您只需要确保要复制的对象确实是一个对象而不仅仅是一个值。
The answer I linked uses their own isObject
for this. 我链接的答案使用自己的
isObject
。 Object filling is done recursively with Object.assign
使用
Object.assign
递归方式完成对象填充
You can use for..of
loop, Object.keys()
to check if property of passed object is an object, if true recursively call function with original object, passed object and key of passed object as parameters then assign property to original object, else check if property does not exist in original object, if true assign passed property to original object. 你可以使用
for..of
循环, Object.keys()
来检查传递对象的属性是否是一个对象,如果true是递归调用原始对象的函数,传递对象和传递对象的键作为参数然后将属性赋值给原始对象, else检查原始对象中是否存在属性,如果为true,则将传递的属性赋值给原始对象。
var precreated1 = { hello: { there: true } }; var precreated2 = { hello: "world" }; function addProps(props, obj, key) { for (let prop of Object.keys(props)) { if (Object.getPrototypeOf(props[prop]) === Object.prototype) { addProps(props[prop], obj, prop) } else { if (key) { obj[key][prop] = props[prop] } else { if (!(prop in obj)) { obj[prop] = props[prop] } } } } } addProps({ hello: { world: true } }, precreated1); console.log("precreated1:", precreated1); addProps({ hello: "there", colour: "green" }, precreated2); console.log("precreated2:", precreated2);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.