【问题标题】:How to join two JavaScript Objects, without using JQUERY [duplicate]如何在不使用 JQUERY 的情况下连接两个 JavaScript 对象 [重复]
【发布时间】:2014-02-22 09:01:54
【问题描述】:

我有两个 json 对象 obj1 和 obj2,我想合并它们并创建一个 json 对象。 生成的 json 应该包含 obj2 中的所有值以及 obj2 中不存在的 obj1 中的值。

Question:

var obj1 = {
    "name":"manu",
    "age":23,
    "occupation":"SE"
}

var obj2 = {
    "name":"manu",
    "age":23,
    "country":"india"
}

Expected:

var result = {
    "name":"manu",
    "age":23,
    "occupation":"SE",
    "country":"india"
}

【问题讨论】:

标签: javascript


【解决方案1】:

有几种不同的解决方案可以实现这一点:

1 - 原生 javascript for-in 循环

const result = {};
let key;

for (key in obj1) {
  if(obj1.hasOwnProperty(key)){
    result[key] = obj1[key];
  }
}

for (key in obj2) {
  if(obj2.hasOwnProperty(key)){
    result[key] = obj2[key];
  }
}

2 - Object.keys()

const result = {};

Object.keys(obj1)
  .forEach(key => result[key] = obj1[key]);

Object.keys(obj2)
  .forEach(key => result[key] = obj2[key]);

3 - Object.assign()
(浏览器兼容性:Chrome:45,Firefox (Gecko):34,Internet Explorer:不支持,Edge:(是),Opera : 32, Safari: 9)

const result = Object.assign({}, obj1, obj2);

4 - Spread Operator
标准化自ECMAScript 2015 (6th Edition, ECMA-262)

在规范的几个部分中定义:Array InitializerArgument Lists

使用这种新语法,您可以像这样将不同的对象加入/合并到一个对象中:

const result = {
  ...obj1,
  ...obj2,
};

5 - jQuery.extend(target, obj1, obj2)

将两个或多个对象的内容合并到第一个对象中。

const target = {};

$.extend(target, obj1, obj2);

6 - jQuery.extend(true, target, obj1, obj2)

将两个或多个对象的内容深度合并到目标中。不支持为第一个参数传递 false

const target = {};

$.extend(true, target, obj1, obj2);

7 - Lodash _.assignIn(object, [sources]):也称为_.extend

const result = {};

_.assignIn(result, obj1, obj2);

8 - Lodash _.merge(object, [sources])

const result = _.merge(obj1, obj2);

lodash 的合并功能和Object.assign 有几个重要的区别:

1- 尽管它们都接收任意数量的对象,但 lodash 的合并应用了这些对象的深度合并,但 Object.assign 仅合并第一级。例如:

_.isEqual(_.merge({
  x: {
    y: { key1: 'value1' },
  },
}, {
  x: {
    y: { key2: 'value2' },
  },
}), {
  x: {
    y: {
      key1: 'value1',
      key2: 'value2',
    },
  },
}); // true

但是:

const result = Object.assign({
  x: {
    y: { key1: 'value1' },
  },
}, {
  x: {
    y: { key2: 'value2' },
  },
});
_.isEqual(result, {
  x: {
    y: {
      key1: 'value1',
      key2: 'value2',
    },
  },
}); // false
// AND
_.isEqual(result, {
  x: {
    y: {
      key2: 'value2',
    },
  },
}); // true

2- 另一个区别与 Object.assign_.merge 如何解释 undefined 值有关:

_.isEqual(_.merge({x: 1}, {x: undefined}), { x: 1 }) // false

但是:

_.isEqual(Object.assign({x: 1}, {x: undefined}), { x: undefined })// true

更新 1:

在 JavaScript 中使用 for in 循环时,我们应该特别注意我们的环境,特别是 JavaScript 类型中可能发生的原型更改。例如,一些较旧的 JavaScript 库向 Array.prototype 甚至 Object.prototype 添加了新内容。 为了保护您的迭代免受添加的东西的影响,我们可以使用object.hasOwnProperty(key) 来确保密钥实际上是您正在迭代的对象的一部分。


更新 2:

我更新了我的答案并添加了解决方案 4,这是一个新的 JavaScript 功能,但尚未完全标准化。我将它与Babeljs 一起使用,这是一个用于编写下一代 JavaScript 的编译器。


更新 3:
我添加了Object.assign_.merge 之间的区别。

【讨论】:

  • 对我来说,只有这种方法有效:$.extend( true, object1, object2 );(递归合并 object2 到 object1)。参考:researchhubs.com/post/computing/javascript/…
  • ^ 可能需要注意哪些方法合并超过第一级,换句话说,递归。
【解决方案2】:

WORKING FIDDLE

使用 Jquery 的最简单方法 -

var finalObj = $.extend(obj1, obj2);

没有 Jquery -

var finalobj={};
for(var _obj in obj1) finalobj[_obj ]=obj1[_obj];
for(var _obj in obj2) finalobj[_obj ]=obj2[_obj];

【讨论】:

【解决方案3】:

我过去曾使用此函数合并对象,我使用它来添加或更新 obj1 上的现有属性,并使用来自 obj2 的值:

var _mergeRecursive = function(obj1, obj2) {

      //iterate over all the properties in the object which is being consumed
      for (var p in obj2) {
          // Property in destination object set; update its value.
          if ( obj2.hasOwnProperty(p) && typeof obj1[p] !== "undefined" ) {
            _mergeRecursive(obj1[p], obj2[p]);

          } else {
            //We don't have that level in the heirarchy so add it
            obj1[p] = obj2[p];

          }
     }
}

它将处理多个层次的层次结构以及单级对象。我将它用作操作 JSON 对象的实用程序库的一部分。你可以找到它here

【讨论】:

  • 我假设你当时写了那个库?
  • 是的,但您的堆栈溢出创作技能似乎让我感到羞耻。感谢对代码示例@matsjoyce 的所有修复
  • 别担心,我只是个格式怪胎(不过我自己也犯了错误)。 This 很有用。
  • 这绝对是一个书签!谢谢@matsjoyce
【解决方案4】:

使用underscore.js 的另一种解决方案:

_.extend({}, obj1, obj2);

【讨论】:

    【解决方案5】:

    1)

    var merged = {};
    for(key in obj1)
        merged[key] = obj1[key];
    for(key in obj2)
        merged[key] = obj2[key];
    

    2)

    var merged = {};
    Object.keys(obj1).forEach(k => merged[k] = obj1[k]);
    Object.keys(obj2).forEach(k => merged[k] = obj2[k]);
    

    Object.keys(obj1)
        .concat(Object.keys(obj2))
        .forEach(k => merged[k] = k in obj2 ? obj2[k] : obj1[k]);
    

    3) 最简单的方法:

    var merged = {};
    Object.assign(merged, obj1, obj2);
    

    【讨论】:

    • 请注意 Object.assign() 确实返回一个值,因此您也可以将 #3 写为:var merged = Object.assign({}, obj1, obj2); 实际上可能性能稍差一些,但可能需要可读性取决于它周围的代码。
    【解决方案6】:

    这个简单的函数递归合并 JSON 对象,请注意这个函数将所有 JSON 合并到第一个参数 (target),如果您需要新对象修改此代码。

    var mergeJSON = function (target, add) {
        function isObject(obj) {
            if (typeof obj == "object") {
                for (var key in obj) {
                    if (obj.hasOwnProperty(key)) {
                        return true; // search for first object prop
                    }
                }
            }
            return false;
        }
        for (var key in add) {
            if (add.hasOwnProperty(key)) {
                if (target[key] && isObject(target[key]) && isObject(add[key])) {
                    this.mergeJSON(target[key], add[key]);
                } else {
                    target[key] = add[key];
                }
            }
        }
        return target;
    };
    

    顺便说一句,而不是isObject() 函数可以使用这样的条件:

    JSON.stringify(add[key])[0] == "{"
    

    但这不是一个好的解决方案,因为如果我们有大型 JSON 对象,它将占用大量资源。

    【讨论】:

    • 请补充说明
    • 这个功能 mergeJSON 为我工作,非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 1970-01-01
    • 2019-09-06
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    相关资源
    最近更新 更多