81

我有多个JSON这样的

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

它们不是嵌套或类似的东西。只是基本上不同的领域。JSON我需要在node.js中将它们组合成一个,如下所示:

{name: "John", location: "San Jose"}

我可以很好地使用jQuery 。这是浏览器中的一个工作示例:

http://jsfiddle.net/qhoc/agp54/

但是如果我在node.js中执行此操作,我不想加载 jQuery(这有点过度使用,加上node.js 的 jQuery在我的Windows机器上不起作用)。

那么有没有一种简单的方法来做类似于$.extend()没有jQuery的事情?

4

18 回答 18

132

你应该使用“ Object.assign()

对于这样一个简单的浅合并用例,无需重新发明轮子。

Object.assign() 方法用于将所有可枚举自身属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed

甚至来自Node.js 的人也这么说

_extend从未打算在内部 NodeJS 模块之外使用。社区还是找到并使用了它。它已被弃用,不应在新代码中使用。JavaScript 通过Object.assign.


更新:

您可以使用扩展运算符

8.6 版本开始,可以在 Node.js 中原生使用扩展运算符。下面的例子:

let o1 = { a: 1 };
let o2 = { b: 2 };
let obj = { ...o1, ...o2 }; // { a: 1, b: 2 }

Object.assign不过,仍然有效。


PS1:如果你真的对深度合并感兴趣(其中内部对象数据——在任何深度——被递归地合并),你可以使用像deepmergeassign-deeplodash.merge这样的包,它们非常小而且简单采用。

PS2:请记住Object.assign 不适用于 0.X 版本的 Node.js。如果您正在使用其中一个版本(您现在真的不应该使用),您可以require("util")._extend按照上面的 Node.js 链接所示使用——有关更多详细信息,请查看tobymackenzie 对同一问题的回答

于 2016-05-20T01:34:13.100 回答
58

如果使用节点版本 >= 4,请使用Object.assign()(参见Ricardo Nolde 的回答)。

如果使用 Node 0.x,则有内置的 util._extend:

var extend = require('util')._extend
var o = extend({}, {name: "John"});
extend(o,  {location: "San Jose"});

它不进行深度复制,一次只允许两个参数,但是是内置的。我在一个关于在节点中克隆对象的问题上看到了这一点:https ://stackoverflow.com/a/15040626 。

如果您担心使用“私有”方法,您可以随时代理它:

// myutil.js
exports.extend = require('util')._extend;

如果它消失了,用你自己的实现替换它。这是(大约)他们的实现:

exports.extend = function(origin, add) {
    if (!add || (typeof add !== 'object' && add !== null)){
        return origin;
    }

    var keys = Object.keys(add);
    var i = keys.length;
    while(i--){
        origin[keys[i]] = add[keys[i]];
    }
    return origin;
};
于 2014-03-09T18:38:32.897 回答
51

就像詹姆斯评论的那样,下划线extend是实现这一目标的最简单和最快的方法。

下面是一个使用下划线的例子:

var _ = require('underscore'), // npm install underscore to install
  object1 = {name: "John"},
  object2 = {location: "San Jose"};

var target = _.extend(object1, object2);

对象 1 将获取对象 2 的属性并返回并分配给目标。你也可以这样做,这取决于你是否介意 object1 被修改:

var target = {};
_.extend(target, object1, object2);
于 2013-02-20T09:21:29.367 回答
42

正常循环?

function extend(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
}

var object3 = extend({}, object1, object2);

这是一个基本的起点。您可能想要添加诸如hasOwnProperty检查之类的东西,或者添加一些逻辑来处理多个源对象具有具有相同标识符的属性的情况。

这是一个工作示例

旁注:您所说的“JSON”实际上是普通的 JavaScript 对象。JSON 只是一种与 JavaScript 共享一些语法的文本格式。

于 2013-02-20T08:01:49.240 回答
15

使用合并

$ npm install merge

示例代码:

var merge = require('merge'), // npm install -g merge
    original, cloned;

console.log(

    merge({ one: 'hello' }, { two: 'world' })

); // {"one": "hello", "two": "world"}

original = { x: { y: 1 } };

cloned = merge(true, original);

cloned.x.y++;

console.log(original.x.y, cloned.x.y); // 1, 2
于 2014-01-16T22:47:48.097 回答
12

我看到这个线程太旧了,但我把我的答案放在这里只是为了记录目的。

在上面的评论之一中,您提到您想在项目中使用“express”,该项目在依赖项列表中有“connect”库。实际上'connect.utils'库包含一个'merge'方法可以解决问题。因此,您无需添加任何新的 3rd 方库即可使用 3rd 方实现。

于 2013-08-25T13:33:22.710 回答
11

这是合并 JSON 的简单解决方案。我做了以下。

  • 使用 . 将每个 JSON 转换为字符串JSON.stringify(object)
  • 使用运算符连接所有 JSON 字符串+
  • 将模式替换/}{/g","
  • 将结果字符串解析回 JSON 对象

    var object1 = {name: "John"};
    var object2 = {location: "San Jose"};
    var merged_object = JSON.parse((JSON.stringify(object1) + JSON.stringify(object2)).replace(/}{/g,","))
    

生成的合并 JSON 将是

{name: "John", location: "San Jose"}
于 2013-02-20T11:52:34.130 回答
3

你也可以使用这个轻量级的 npm 包,叫做吸收

它是 27 行代码,1kb,并使用递归来执行深度对象合并。

var absorb = require('absorb');
var obj1, obj2;

obj1 = { foo: 123, bar: 456 };
obj2 = { bar: 123, key: 'value' }

absorb(obj1, obj2);

console.log(obj1); // Output: { foo: 123, bar: 123, key: 'value' }

您还可以使用它来进行克隆或仅在源对象中不存在值时才传输值,如何执行此操作在提供的链接中进行了详细说明。

于 2015-08-04T19:03:13.060 回答
3

使用 Object.assign() 方法可以轻松完成 -

 var object1 = {name: "John"};
 var object2 = {location: "San Jose"};
 var object3 = Object.assign(object1,object2);
 console.log(object3);

现在 object3 是 { name: 'John', location: 'San Jose' }

于 2016-12-20T10:02:06.953 回答
3

在 Node.js 中有一种简单的方法

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

要组合/扩展它,我们可以...在 ECMA6 中使用运算符

var object1 = {name: "John"};
var object2 = {location: "San Jose"};

var result = {
  ...object1,
  ...object2
}

console.log(result)

于 2018-04-13T04:12:40.483 回答
2

如果您需要嵌套对象扩展或数组替换等特殊行为,您可以使用 Node.js 的extendify

var extendify = require('extendify');

_.extend = extendify({
    inPlace: false,
    arrays : 'replace',
    isDeep: true
});

obj1 = {
    a:{
        arr: [1,2]
    },
    b: 4
};

obj2 = {
    a:{
        arr: [3]
    }
};

res = _.extend(obj1,obj2);
console.log(JSON.stringify(res)); //{'a':{'arr':[3]},'b':4}
于 2014-07-06T17:53:42.793 回答
2

Lodash是此类实用程序的另一个强大的工具带选项。请参阅:(_.merge()这是递归的)

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
}; 
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } 
于 2016-09-05T21:14:49.473 回答
2

使用扩展运算符。从 8.6 版开始在 Node 中支持

const object1 = {name: "John"};
const object2 = {location: "San Jose"};

const obj = {...object1, ...object2}

console.log(obj)
//   {
//     "name": "John",
//     "location": "San Jose"
//   }

于 2018-09-25T14:56:13.213 回答
1

下面的代码将帮助您合并两个具有嵌套对象的 JSON 对象。

function mergeJSON(source1,source2){
    /*
     * Properties from the Souce1 object will be copied to Source2 Object.
     * Note: This method will return a new merged object, Source1 and Source2 original values will not be replaced.
     * */
    var mergedJSON = Object.create(source2);// Copying Source2 to a new Object

    for (var attrname in source1) {
        if(mergedJSON.hasOwnProperty(attrname)) {
          if ( source1[attrname]!=null && source1[attrname].constructor==Object ) {
              /*
               * Recursive call if the property is an object,
               * Iterate the object and set all properties of the inner object.
              */
              mergedJSON[attrname] = zrd3.utils.mergeJSON(source1[attrname], mergedJSON[attrname]);
          } 

        } else {//else copy the property from source1
            mergedJSON[attrname] = source1[attrname];

        }
      }

      return mergedJSON;
}
于 2014-06-17T10:15:07.087 回答
1

你可以使用 Lodash

const _ = require('lodash');

let firstObject = {'email' : 'email@email.com};
let secondObject = { 'name' : { 'first':message.firstName } };
_.merge(firstObject, secondObject)
于 2017-01-23T21:16:10.690 回答
0

为了不改变目标,从正确的解决方案中获得更好的方法:

function extend(){
  let sources = [].slice.call(arguments, 0), result = {};
  sources.forEach(function (source) {
    for (let prop in source) {
      result[prop] = source[prop];
    }
  });
  return result;
}
于 2017-11-07T15:53:37.207 回答
0

您可以内联执行此操作,而无需更改任何变量,如下所示:

let obj1 = { name: 'John' };
let obj2 = { surname: 'Smith' };
let obj = Object.assign({}, obj1, obj2); // { name: 'John', surname: 'Smith' }
于 2018-09-25T13:19:16.700 回答
-3

object1object2成为两个 JSON 对象。

var object1 = [{"name": "John"}];
var object2 = [{"location": "San Jose"}];

object1.push(object2);

object2这将简单地追加object1

[{"name":"John"},{"location":"San Jose"}]
于 2016-06-18T11:02:53.337 回答