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

Updating JavaScript object-attributes from another object

本问题已经有最佳答案,请猛点这里访问。

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

1
2
3
4
5
6
7
currentObject = {
    someValue :"value",
    myObject : {
        attribute1 :"foo",
        attribute2 :"bar"
    }
};

…对象包含一些更改,例如:

1
2
3
4
5
updateObject = {
    myObject : {
        attribute2 :"hello world"
    }
};

最后,我想让当前对象更新,以便:

1
currentObject.myObject.attribute2 =="hello world"

对于其他对象也应该是可设置的。作为一个解决方案,我考虑对对象进行迭代,并以某种方式处理名称空间。但我想知道是否有一个简单的解决方案,通过使用类似jquery或原型的库来解决这个问题。


我建议用underscore.js(或更好,罗extend短跑): P / < >

_.extend(destination, *sources)

Copy all of the properties in the source objects over to the
destination object, and return the destination object. It's in-order,
so the last source will override properties of the same name in
previous arguments.

1
2
_.extend({name: 'moe'}, {age: 50});
=> {name: 'moe', age: 50}


1
2
3
4
5
6
7
8
9
10
11
12
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到extend只真正的物体与真实的物体,使用的是的先生为arrays环或hasOwnProperty试验。 P / < >


简单的实施会看起来像这样的。 P / < >

1
2
3
4
5
6
7
8
9
10
11
12
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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];
}

这assumes没有inherited性质应该cloned。它也确实没有-事情像DOM的物体,或boxed primitives。 P / < >

我们需要在iterate逆向通过arguments如此,拷贝也在做正确的事是怎样的。 P / < >

然后让我们的separate cloneObject功能到处理的recursive copying的物体在一个嵌套的方式,并不interfere T与右到左copying之原arguments对象。 P / < >

它也ensures,初始目标对象的平原。 P / < >

"cloneObject功能将把一个错误的对象是时代不同了,如果不到它。 P / < >


这里的一个Object.keys和recursive的例子: P / < >

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 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演示。 P / < >