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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12534238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 10:38:43  来源:igfitidea点击:

Updating JavaScript object-attributes from another object

javascriptobjectpropertieskey

提问by Luca Hofmann

I want to update an object that could look like this:

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

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

.. with an object that contains some changes i.e.:

.. 使用包含一些更改的对象,即:

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

At the end I would like to have currentObject updated so that:

最后,我希望更新 currentObject 以便:

currentObject.myObject.attribute2 == "hello world"

That should be posible for other objects as well.. As a solution I thought about iterating over the object and somehow take care of the namespace. But I wonder if there is an easy solution for that problem by using a library like jQuery or prototype.

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

采纳答案by Bergi

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;
}

should do the trick: update(currentObject, updateObject). You might want to add some type checks, like Object(obj) === objto extend only real objects with real objects, use a correct loop for arrays or hasOwnPropertytests.

应该做的伎俩:update(currentObject, updateObject)。您可能想要添加一些类型检查,例如Object(obj) === obj仅使用真实对象扩展真实对象,对数组或hasOwnProperty测试使用正确的循环。

回答by bluehallu

I suggest using underscore.js (or better, lo-dash) extend:

我建议使用 underscore.js(或更好的 lo-dash)扩展

_.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.

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

_.extend(目的地,*来源)

将源对象中的所有属性复制到目标对象,并返回目标对象。它是有序的,所以最后一个源将覆盖前面参数中同名的属性

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

回答by Bergi

A simple implementation would look like this.

一个简单的实现看起来像这样。

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];
}

This assumes no inherited properties should be cloned. It also does no checks for things like DOM objects, or boxed primitives.

这假设不应克隆继承的属性。它也不检查诸如 DOM 对象或装箱基元之类的东西。

We need to iterate in reverse through the arguments so that the copy is done in a right to left matter.

我们需要反向迭代参数,以便从右到左完成复制。

Then we make a separate cloneObjectfunction to handle the recursive copying of nested objects in a manner that doesn't interfere with the right to left copying of the original object arguments.

然后我们创建一个单独的cloneObject函数来处理嵌套对象的递归复制,这种方式不会干扰原始对象参数的从右到左复制。

It also ensures that the initial target is a plain object.

它还确保初始目标是一个普通对象。

The cloneObjectfunction will throw an error if a non-object was passed to it.

cloneObject如果将非对象传递给该函数,则该函数将引发错误。

回答by bloodyKnuckles

Here's an Object.keysand recursive example:

这是一个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.

JSFiddle 演示