【发布时间】:2020-07-10 19:00:21
【问题描述】:
我一直在尝试在缺少属性的情况下初始化一个对象,就像我们使用 OR 运算符对变量所做的那样:
var finalValue = myVariable || 'hello there'
我找到了很多关于如何使用 Object.assign() 方法的回复:
finalObject = Object.assign({}, defaultObject, myObject)
不过,当涉及到具有嵌套数据的对象时,我还是没有找到合适的解决方案。这是我想出的:
var arrayConstructor = [].constructor;
var objectConstructor = ({}).constructor;
var whatIsIt = function(object) {
if (object === null) {
return "null";
} else
if (object === undefined) {
return "undefined";
} else
if (object.constructor === arrayConstructor) {
return "array";
} else
if (object.constructor === objectConstructor) {
return "object";
} else {
return "normal variable";
}
}
var copyWithValidation = function(jsonObject, defaultValues) {
let defaultKeys = Object.keys(defaultValues);
let returnValue = Object.assign({}, defaultValues, jsonObject);
// Check for json object
defaultKeys.map((key) => {
switch (whatIsIt(defaultValues[key])) {
case 'object':
if (!jsonObject.hasOwnProperty(key)) {
jsonObject[key] = {};
}
returnValue[key] = copyWithValidation(jsonObject[key], defaultValues[key]);
break;
case 'array':
if (jsonObject.hasOwnProperty(key)) {
returnValue[key] = [...jsonObject[key]];
} else {
returnValue[key] = [...defaultValues[key]];
}
break;
default:
break;
}
});
return returnValue;
}
// My default object
var def1 = {
label1: '',
label2: '',
label3: '',
sublabels: {
label1: '',
label2: '',
label3: '',
},
sublabels2: {
label1: '',
label2: '',
label3: '',
label4: {
title: '',
subtitle: '',
},
},
sublabels3: {
label1: [],
label2: [],
label3: [],
},
}
// The object we want to initialize
var j1 = {
label1: 'hello1',
label2: 'hello2',
sublabels: {
label2: 'subhello2',
label3: 'subhello3',
},
sublabels3: {
label1: ['subhello1', 'subhello2', 'subhello3'],
label4: {
title: 'Hello there!',
subtitle: 'Hello there again',
},
},
}
// Let's run the script!
let p = copyWithValidation(j1, def1);
console.log(p);
整个想法是在对象中进行遍历,并最初使用“Object.assign({}, defaultValues, jsonObject)”方法来“复制”特定级别的属性。之后,我正在检查是否有对象或数组。
如果是对象,我将 {} 设置为目标对象(以防属性不存在)并在该对象内调用相同的 copyWithValidation() 方法;递归它将涵盖所有级别。
如果是数组,我只是使用扩展运算符。有趣的是,这甚至适用于作为数组元素的对象。
不确定是否有更高效的代码可以返回相同的结果。
感谢 Aamir Afridi 和 Joaquin Keller 使用/组合他们的脚本。
【问题讨论】:
-
如果你愿意使用库,lodash 的merge 完全符合你的要求
-
仅当每个键存在于
.map中而不是使用 Object.assign 时才复制它可能仍然更有效,因为它避免了重新复制重复的键,并且至少在 V8 下 Object.assign 是仍然比仅使用 Object spread 慢,这仍然比仅复制您需要的属性要慢,并且它会在default:之后的一行。它也不再简洁,因为无论如何您都需要循环和迭代键。另外,您没有使用.map的返回值,因此您应该使用.forEach或for-of 循环
标签: javascript node.js object