我想更新一个看起来像这样的对象:
currentObject = {
someValue : "value",
myObject : {
attribute1 : "foo",
attribute2 : "bar"
}
};
..包含一些包含一些变化的对象,例如:
updateObject = {
myObject : {
attribute2 : "hello world"
}
};
最后,我想更新currentObject,以便:
currentObject.myObject.attribute2 == "hello world"
这也应该适用于其他物体.. 作为一个解决方案,我考虑迭代对象,并以某种方式处理命名空间。但我想知道是否通过使用像jQuery或原型这样的库来解决这个问题。
答案 0 :(得分:16)
我建议使用underscore.js(或更好,lo-dash)extend:
_.extend(destination,* sources)
将源对象中的所有属性复制到 目标对象,并返回目标对象。 这是有序的, 所以最后一个源将覆盖相同名称的属性 以前的论点 。
_.extend({name: 'moe'}, {age: 50}); => {name: 'moe', age: 50}
答案 1 :(得分:9)
function update(obj/*, …*/) {
for (var i=1; i<arguments.length; i++) {
for (var prop in arguments[i]) {
var val = arguments[i][prop];
if (typeof val == "object") // this also applies to arrays or null!
update(obj[prop], val);
else
obj[prop] = val;
}
}
return obj;
}
应该做的伎俩:update(currentObject, updateObject)
。您可能希望添加一些类型检查,例如Object(obj) === obj
以仅扩展具有真实对象的真实对象,使用正确的数组循环或hasOwnProperty
测试。
答案 2 :(得分:1)
一个简单的实现看起来像这样。
function copyInto(target /*, source1, sourcen */) {
if (!target || typeof target !== "object")
target = {};
if (arguments.length < 2)
return target;
for (var len = arguments.length - 1; len > 0; len--)
cloneObject(arguments[len-1], arguments[len]);
return target;
}
function cloneObject(target, source) {
if (!source || !target || typeof source !== "object" || typeof target !== "object")
throw new TypeError("Invalid argument");
for (var p in source)
if (source.hasOwnProperty(p))
if (source[p] && typeof source[p] === "object")
if (target[p] && typeof target[p] === "object")
cloneObject(target[p], source[p]);
else
target[p] = source[p];
else
target[p] = source[p];
}
这假设不应该克隆任何继承的属性。它也不会检查DOM对象或盒装基元等内容。
我们需要通过参数反向迭代,以便从右到左完成复制。
然后我们创建一个单独的cloneObject
函数来处理嵌套对象的递归复制,其方式不会干扰原始对象参数的从右到左复制。
它还确保初始目标是普通对象。
如果传递了非对象,cloneObject
函数将抛出错误。
答案 3 :(得分:0)
这是一个Object.keys
和递归示例:
// execute object update function
update(currentObject, updateObject)
// instantiate object update function
function update (targetObject, obj) {
Object.keys(obj).forEach(function (key) {
// delete property if set to undefined or null
if ( undefined === obj[key] || null === obj[key] ) {
delete targetObject[key]
}
// property value is object, so recurse
else if (
'object' === typeof obj[key]
&& !Array.isArray(obj[key])
) {
// target property not object, overwrite with empty object
if (
!('object' === typeof targetObject[key]
&& !Array.isArray(targetObject[key]))
) {
targetObject[key] = {}
}
// recurse
update(targetObject[key], obj[key])
}
// set target property to update property
else {
targetObject[key] = obj[key]
}
})
}