从另一个对象更新JavaScript对象属性

时间:2012-09-21 16:15:27

标签: javascript object properties key

我想更新一个看起来像这样的对象:

currentObject = {
    someValue : "value",
    myObject : {
        attribute1 : "foo",
        attribute2 : "bar"
    }
};

..包含一些包含一些变化的对象,例如:

updateObject = {
    myObject : {
        attribute2 : "hello world"
    }
};

最后,我想更新currentObject,以便:

currentObject.myObject.attribute2 == "hello world"

这也应该适用于其他物体.. 作为一个解决方案,我考虑迭代对象,并以某种方式处理命名空间。但我想知道是否通过使用像jQuery或原型这样的库来解决这个问题。

4 个答案:

答案 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]
    }
  })
}

JSFiddle demo