从另一个对象更新 JavaScript 对象属性 [重复]

Posted

技术标签:

【中文标题】从另一个对象更新 JavaScript 对象属性 [重复]【英文标题】:Updating JavaScript object-attributes from another object [duplicate] 【发布时间】:2012-09-14 02:17:02 【问题描述】:

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

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

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

updateObject = 
    myObject : 
        attribute2 : "hello world"
    
;

最后我想更新 currentObject 以便:

currentObject.myObject.attribute2 == "hello world"

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

【问题讨论】:

如果你使用 jQuery,$.extend 应该可以满足你的需求。 @RocketHazmat:不,它不是递归的。 @Bergi:如果您将true 作为第一个参数传递,那就是! ;-) @Bergi 在您声明之前请先查一下。这是一个链接,您可以阅读有关.extend的信息:api.jquery.com/jQuery.extend @RocketHazmat:是的,我总是忘记这一点(我不太喜欢这个函数,因为它的数组处理) 【参考方案1】:

我建议使用 underscore.js(或者更好,lo-dash)extend:

_.extend(destination, *sources)

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

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

【讨论】:

据我所知,Underscore 和 Lodash 的 extend 都将覆盖 myObject 属性,而不是简单地更新它(即它将包含 only @987654325 @)。但是,Lodash 的 merge 会起作用。 正如@Tata​​Black 所指出的,给定var a = name: 'moe', age: 50, b = age: 30; var c = _.merge(, a, b);c 将是name: 'moe', age: 30,而ab 保持不变。【参考方案2】:
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 测试。

【讨论】:

【参考方案3】:

这是一个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(打开控制台)。

【讨论】:

【参考方案4】:

一个简单的实现如下所示。

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 函数如果传递了一个非对象将抛出一个错误。

【讨论】:

为什么要从源到源再到……再到目标? @Bergi:我猜只是一种不同的方法,但我确实认为我应该通过创建临时对象而不是修改原始对象来使其成为非破坏性的。另外,如果有foo:[...] &lt;- foo:... 的情况,我应该真正区分数组和对象。 是的,它对源应该是非破坏性的 - 但您不需要临时对象,只需 cloneInto(target)。是的,用数组扩展普通对象很痛苦:-)

以上是关于从另一个对象更新 JavaScript 对象属性 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

理解JavaScript 的原型属性

从另一个对象调用时 UIImage 不更新

在Google Apps脚本和javascript / jQuery中从另一个对象或数组构建对象

一旦从另一个线程获得结果,如何更新领域对象?

模板中的 Django 字典:从另一个对象属性中获取键

从另一个对象观察 @Published 变量