【问题标题】:Updating JavaScript object-attributes from another object [duplicate]从另一个对象更新 JavaScript 对象属性 [重复]
【发布时间】: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:是的,我总是忘记这一点(我不太喜欢这个函数,因为它的数组处理)

标签: javascript object properties key


【解决方案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)。是的,用数组扩展普通对象很痛苦:-)
      猜你喜欢
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      • 2016-10-13
      • 2020-11-06
      • 2012-03-16
      • 2016-07-13
      • 1970-01-01
      相关资源
      最近更新 更多