Как я могу динамически объединить свойства двух объектов JavaScript?

Мне нужно объединить два (очень простых) объекта JavaScript во время выполнения. Например, я бы хотел:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

obj1.merge(obj2);

//obj1 now has three properties: food, car, and animal

У кого-нибудь есть сценарий для этого или есть встроенный способ сделать это? Мне не нужна рекурсия, и мне не нужно объединять функции, а только методы на плоских объектах.


person Community    schedule 05.10.2008    source источник
comment
Стоит отметить этот ответ на аналогичный вопрос, в котором показано, как объединить на один уровень ниже. То есть он объединяет значения повторяющихся ключей (вместо перезаписи первого значения вторым значением), но не выполняет рекурсию дальше этого. IMHO, это хороший чистый код для этой задачи.   -  person ToolmakerSteve    schedule 04.10.2019
comment
Кстати, несколько верхних ответов выполняют неглубокое слияние: если один и тот же ключ существует как в obj1, так и в obj2, значение в obj2 сохраняется, значение в obj1 отбрасывается. Например. если в примере вопроса было var obj2 = { animal: 'dog', food: 'bone' };, слияние будет { food: 'bone', car: 'ford', animal: 'dog' }. Если вы работаете с вложенными данными и хотите глубокое слияние, поищите ответы, в которых упоминается глубокое слияние или рекурсия. Если у вас есть значения, равные arrays, используйте параметр arrayMerge в github TehShrike / deepmerge, как упоминалось здесь.   -  person ToolmakerSteve    schedule 04.10.2019
comment
Перейдите по ссылке ниже stackoverflow.com/questions/171251/ Оператор распространения, который является новой функцией в версии ES6   -  person Soura Sankar Ghosh    schedule 11.01.2020


Ответы (64)


Стандартный метод ECMAScript 2018

Вы должны использовать распространение объекта:

let merged = {...obj1, ...obj2};

merged теперь объединение obj1 и obj2. Свойства в obj2 перезапишут свойства в obj1.

/** There's no limit to the number of objects you can merge.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = {...obj1, ...obj2, ...obj3};

Здесь также есть документация по MDN для этого синтаксиса. . Если вы используете babel, вам понадобится babel- plugin-transform-object-rest-spread, чтобы он работал.

Стандартный метод ECMAScript 2015 (ES6)

/* For the case in question, you would do: */
Object.assign(obj1, obj2);

/** There's no limit to the number of objects you can merge.
 *  All objects get merged into the first object. 
 *  Only the object in the first argument is mutated and returned.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = Object.assign({}, obj1, obj2, obj3, etc);

(см. Справочник по MDN JavaScript )


Метод для ES5 и более ранних версий

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

Обратите внимание, что это просто добавит все атрибуты obj2 в obj1, что может быть не тем, что вам нужно, если вы все еще хотите использовать неизмененный obj1.

Если вы используете фреймворк, который не справляется со всеми вашими прототипами, вам нужно стать более привлекательным с проверками типа hasOwnProperty, но этот код будет работать в 99% случаев.

Пример функции:

/**
 * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
 * @param obj1
 * @param obj2
 * @returns obj3 a new object based on obj1 and obj2
 */
function merge_options(obj1,obj2){
    var obj3 = {};
    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
    return obj3;
}
person Community    schedule 05.10.2008
comment
Это не работает, если объекты имеют атрибуты с одинаковыми именами, и вы также можете объединить атрибуты. - person Xiè Jìléi; 24.10.2010
comment
Это только поверхностное копирование / слияние. Имеет потенциал уничтожить множество элементов. - person Jay Taylor; 02.06.2011
comment
+1 за признание того, что некоторые бедняги вынуждены использовать фреймворки, которые гадят на всех их прототипах ... - person thejonwithnoh; 07.05.2016

В jQuery также есть утилита для этого: http://api.jquery.com/jQuery.extend/.

Взято из документации jQuery:

// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options  = { validate: true, name: "bar" };
jQuery.extend(settings, options);

// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }

Приведенный выше код изменит существующий объект с именем settings.


Если вы хотите создать новый объект, не изменяя ни один из аргументов, используйте это:

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);

// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.
person Community    schedule 05.10.2008
comment
Будьте осторожны: настройки переменных будут изменены. jQuery не возвращает новый экземпляр. Причина этого (и именования) в том, что .extend () был разработан для расширения объектов, а не для объединения вещей вместе. Если вам нужен новый объект (например, настройки по умолчанию, которые вы не хотите трогать), вы всегда можете jQuery.extend ({}, settings, options); - person webmat; 04.05.2011
comment
Имейте в виду, что jQuery.extend также имеет глубокую (логическую) настройку. jQuery.extend(true,settings,override), что важно, если свойство в настройках содержит объект, а переопределение имеет только часть этого объекта. Вместо удаления несогласованных свойств глубокая настройка будет обновляться только там, где она существует. По умолчанию - false. - person vol7ron; 10.06.2011

Harmony ECMAScript 2015 (ES6) указывает Object.assign, который сделаю это.

Object.assign(obj1, obj2);

Текущая поддержка браузера становится лучше, но если вы разрабатывая для браузеров, у которых нет поддержки, вы можете использовать полифил.

person Community    schedule 05.10.2014
comment
Обратите внимание, что это только неглубокое слияние - person Joachim Lous; 16.03.2016
comment
Я думаю, что тем временем Object.assign имеет довольно приличный охват: kangax.github.io/ compat-table / es6 / - person brass monkey; 26.05.2016
comment
Теперь это должен быть правильный ответ. В настоящее время люди компилируют свой код для совместимости с редким браузером (IE11), который не поддерживает такого рода вещи. Боковое примечание: если вы не хотите добавлять obj2 в obj1, вы можете вернуть новый объект, используя Object.assign({}, obj1, obj2) - person Duvrai; 21.07.2016
comment
@Duvrai Согласно отчетам, которые я видел, IE11 определенно не редкость, составляя около 18% рынка по состоянию на июль 2016 года. - person NanoWizard; 08.08.2016

Я искал код для объединения свойств объекта и оказался здесь. Однако, поскольку не было кода для рекурсивного слияния, я написал его сам. (Может быть, расширение jQuery является рекурсивным, кстати?) В любом случае, надеюсь, кто-то еще сочтет это полезным.

(Теперь в коде не используется Object.prototype :)

Код

/*
* Recursively merge properties of two objects 
*/
function MergeRecursive(obj1, obj2) {

  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);

      } else {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

Пример

o1 = {  a : 1,
        b : 2,
        c : {
          ca : 1,
          cb : 2,
          cc : {
            cca : 100,
            ccb : 200 } } };

o2 = {  a : 10,
        c : {
          ca : 10,
          cb : 20, 
          cc : {
            cca : 101,
            ccb : 202 } } };

o3 = MergeRecursive(o1, o2);

Создает объект o3 как

o3 = {  a : 10,
        b : 2,
        c : {
          ca : 10,
          cb : 20,
          cc : { 
            cca : 101,
            ccb : 202 } } };
person Community    schedule 20.12.2008
comment
Хорошо, но сначала я бы сделал глубокую копию объектов. Таким образом, o1 также будет изменен, поскольку объекты передаются по ссылке. - person skerit; 16.01.2011

Обратите внимание, что underscore.js extend-method делает это однострочно:

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
person Community    schedule 19.02.2012
comment
Этот пример хорош, поскольку вы имеете дело с анонимными объектами, но если это не так, тогда webmat комментарий в ответе jQuery предупреждение о мутациях применяется здесь, как и подчеркивание изменяет целевой объект. Как и в случае с ответом jQuery, чтобы сделать это без мутаций, просто слейтесь с пустым объектом: _({}).extend(obj1, obj2); - person Abe Voelker; 05.06.2012

Подобно jQuery extend (), у вас есть та же функция в AngularJS:

// Merge the 'options' object into the 'settings' object
var settings = {validate: false, limit: 5, name: "foo"};
var options  = {validate: true, name: "bar"};
angular.extend(settings, options);
person Community    schedule 27.01.2014

Мне нужно объединить объекты сегодня, и этот вопрос (и ответы) мне очень помог. Я попробовал некоторые ответы, но ни один из них не соответствовал моим потребностям, поэтому я объединил некоторые ответы, добавил что-то сам и придумал новую функцию слияния. Вот:

var merge = function() {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};

Некоторые примеры использования:

var t1 = {
    key1: 1,
    key2: "test",
    key3: [5, 2, 76, 21]
};
var t2 = {
    key1: {
        ik1: "hello",
        ik2: "world",
        ik3: 3
    }
};
var t3 = {
    key2: 3,
    key3: {
        t1: 1,
        t2: 2,
        t3: {
            a1: 1,
            a2: 3,
            a4: [21, 3, 42, "asd"]
        }
    }
};

console.log(merge(t1, t2));
console.log(merge(t1, t3));
console.log(merge(t2, t3));
console.log(merge(t1, t2, t3));
console.log(merge({}, t1, { key1: 1 }));
person Community    schedule 24.12.2011

Для достижения это. Это часть ES2018 и не только.

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

const obj3 = { ...obj1, ...obj2 };
console.log(obj3);

person Community    schedule 27.01.2017
comment
Поддержка браузера? - person Slava; 11.10.2017
comment
@ Alph.Dev Вы знаете caniuse.com? - person connexo; 02.01.2018
comment
Я не могу заставить работать трехточечный синтаксис в node.js. узел жалуется на это. - person klewis; 16.03.2018

Объединить свойства N объектов в одной строке кода

Метод Object.assign является частью стандарта ECMAScript 2015 (ES6) и делает именно то, что вам нужно. (IE не поддерживается)

var clone = Object.assign({}, obj);

Метод Object.assign () используется для копирования значений всех перечислимых собственных свойств из одного или нескольких исходных объектов в целевой объект.

Подробнее…

polyfill для поддержки старых браузеров:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}
person Community    schedule 15.12.2015

Приведенные решения должны быть изменены для проверки source.hasOwnProperty(property) в for..in циклах перед назначением - в противном случае вы в конечном итоге скопируете свойства всей цепочки прототипов, что редко бывает желательно ...

person Community    schedule 21.12.2008

Следующие два, вероятно, являются хорошей отправной точкой. lodash также имеет функцию настройки для этих особых нужд!

_.extend (http://underscorejs.org/#extend)
_.merge (https://lodash.com/docs#merge)

person Community    schedule 30.01.2015

Кстати, все, что вы делаете, - это перезапись свойств, а не слияние ...

Вот как действительно слились области объектов JavaScript: только ключи в объекте to, которые сами не являются объектами, будут перезаписаны from. Все остальное будет действительно объединено. Конечно, вы можете изменить это поведение, чтобы не перезаписывать все, что существует, например, только если to[n] is undefined и т. Д.:

var realMerge = function (to, from) {

    for (n in from) {

        if (typeof to[n] != 'object') {
            to[n] = from[n];
        } else if (typeof from[n] == 'object') {
            to[n] = realMerge(to[n], from[n]);
        }
    }
    return to;
};

Использование:

var merged = realMerge(obj1, obj2);
person Community    schedule 19.09.2012

Вот мой удар, который

  1. Поддерживает глубокое слияние
  2. Не изменяет аргументы
  3. Принимает любое количество аргументов
  4. Не расширяет прототип объекта
  5. Не зависит от другой библиотеки (jQuery, MooTools, Underscore.js и т. д.)
  6. Включает проверку hasOwnProperty
  7. Короткий :)

    /*
        Recursively merge properties and return new object
        obj1 &lt;- obj2 [ &lt;- ... ]
    */
    function merge () {
        var dst = {}
            ,src
            ,p
            ,args = [].splice.call(arguments, 0)
        ;
    
        while (args.length > 0) {
            src = args.splice(0, 1)[0];
            if (toString.call(src) == '[object Object]') {
                for (p in src) {
                    if (src.hasOwnProperty(p)) {
                        if (toString.call(src[p]) == '[object Object]') {
                            dst[p] = merge(dst[p] || {}, src[p]);
                        } else {
                            dst[p] = src[p];
                        }
                    }
                }
            }
        }
    
       return dst;
    }
    

Пример:

a = {
    "p1": "p1a",
    "p2": [
        "a",
        "b",
        "c"
    ],
    "p3": true,
    "p5": null,
    "p6": {
        "p61": "p61a",
        "p62": "p62a",
        "p63": [
            "aa",
            "bb",
            "cc"
        ],
        "p64": {
            "p641": "p641a"
        }
    }
};

b = {
    "p1": "p1b",
    "p2": [
        "d",
        "e",
        "f"
    ],
    "p3": false,
    "p4": true,
    "p6": {
        "p61": "p61b",
        "p64": {
            "p642": "p642b"
        }
    }
};

c = {
    "p1": "p1c",
    "p3": null,
    "p6": {
        "p62": "p62c",
        "p64": {
            "p643": "p641c"
        }
    }
};

d = merge(a, b, c);


/*
    d = {
        "p1": "p1c",
        "p2": [
            "d",
            "e",
            "f"
        ],
        "p3": null,
        "p5": null,
        "p6": {
            "p61": "p61b",
            "p62": "p62c",
            "p63": [
                "aa",
                "bb",
                "cc"
            ],
            "p64": {
                "p641": "p641a",
                "p642": "p642b",
                "p643": "p641c"
            }
        },
        "p4": true
    };
*/
person Community    schedule 23.04.2013

Object.assign ()

ECMAScript 2015 (ES6)

Это новая технология, часть стандарта ECMAScript 2015 (ES6). Спецификация этой технологии завершена, но проверьте таблицу совместимости на предмет использования и статуса реализации в различных браузерах.

Метод 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.
person Community    schedule 16.11.2015

Для не слишком сложных объектов вы можете использовать JSON:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'chevy'}
var objMerge;

objMerge = JSON.stringify(obj1) + JSON.stringify(obj2);

// {"food": "pizza","car":"ford"}{"animal":"dog","car":"chevy"}

objMerge = objMerge.replace(/\}\{/, ","); //  \_ replace with comma for valid JSON

objMerge = JSON.parse(objMerge); // { food: 'pizza', animal: 'dog', car: 'chevy'}
// Of same keys in both objects, the last object's value is retained_/

Имейте в виду, что в этом примере "} {" не должно встречаться внутри строки!

person Community    schedule 26.02.2010

На deepmerge. GitHub "rel =" noreferrer "> GitHub: похоже, это набирает обороты. Это автономный вариант, доступный как через npm, так и через менеджеры пакетов bower.

Я был бы склонен использовать или улучшить это вместо того, чтобы копировать код из ответов.

person Community    schedule 22.06.2014

Лучший способ сделать это - добавить подходящее свойство, которое нельзя перечислить, с помощью Object.defineProperty.

Таким образом, вы по-прежнему сможете перебирать свойства ваших объектов, не имея вновь созданного «расширения», которое вы получили бы, если бы создали свойство с помощью Object.prototype.extend.

Надеюсь, это поможет:

Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

Как только у вас это получится, вы сможете:

var obj = {
    name: 'stack',
    finish: 'overflow'
}
var replacement = {
    name: 'stock'
};

obj.extend(replacement);

Я только что написал об этом в блоге здесь: http://onemoredigit.com/post/1527191998/exnding-objects-in-node-js

person Community    schedule 09.11.2010

Вы можете просто использовать jQuery extend

var obj1 = { val1: false, limit: 5, name: "foo" };
var obj2 = { val2: true, name: "bar" };

jQuery.extend(obj1, obj2);

Теперь obj1 содержит все значения obj1 и obj2

person Community    schedule 31.08.2015

Прототип содержит следующее:

Object.extend = function(destination,source) {
    for (var property in source)
        destination[property] = source[property];
    return destination;
}

obj1.extend(obj2) будет делать то, что вы хотите.

person Community    schedule 05.10.2008

** Объединить объекты просто с помощью Object.assign или оператора распространения ... **

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'BMW' }
var obj3 = {a: "A"}


var mergedObj = Object.assign(obj1,obj2,obj3)
 // or using the Spread operator (...)
var mergedObj = {...obj1,...obj2,...obj3}

console.log(mergedObj);

Объекты объединяются справа налево, это означает, что объекты, которые имеют идентичные свойства, как объекты справа от них, будут переопределены.

В этом примере obj2.car переопределяет obj1.car

person Community    schedule 20.03.2018

Если кто-то использует библиотеку закрытия Google:

goog.require('goog.object');
var a = {'a': 1, 'b': 2};
var b = {'b': 3, 'c': 4};
goog.object.extend(a, b);
// Now object a == {'a': 1, 'b': 3, 'c': 4};

Аналогичная вспомогательная функция существует для массива:

var a = [1, 2];
var b = [3, 4];
goog.array.extend(a, b); // Extends array 'a'
goog.array.concat(a, b); // Returns concatenation of array 'a' and 'b'
person Community    schedule 19.04.2012

Вау ... это первая публикация на StackOverflow, которую я видел с несколькими страницами. Приносим извинения за добавление еще одного ответа


ES5 и более ранние версии

Этот метод предназначен для ES5 и более ранних версий - есть много других ответов, касающихся ES6.

Я не видел глубокого слияния объектов с использованием _ 1_ свойство. Вот мой ответ - компактный и рекурсивный, позволяющий передавать неограниченное количество аргументов объекта:

function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        // Uncomment to skip arguments that are not objects (to prevent errors)
        // if (arguments[i].constructor !== Object) continue;
        for (var k in arguments[i]) {
            if (arguments[i].hasOwnProperty(k)) {
                o[k] = arguments[i][k].constructor === Object
                    ? extend(o[k] || {}, arguments[i][k])
                    : arguments[i][k];
            }
        }
    }
    return o;
}

Пример

/**
 * Extend objects
 */
function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        for (var k in arguments[i]) {
            if (arguments[i].hasOwnProperty(k)) {
                o[k] = arguments[i][k].constructor === Object
                    ? extend(o[k] || {}, arguments[i][k])
                    : arguments[i][k];
            }
        }
    }
    return o;
}

/**
 * Example
 */
document.write(JSON.stringify(extend({
    api: 1,
    params: {
        query: 'hello'
    }
}, {
    params: {
        query: 'there'
    }
})));
// outputs {"api": 1, "params": {"query": "there"}}


Этот ответ - капля в море ...

person Community    schedule 01.05.2018

Я расширил метод Дэвида Коллиера:

  • Добавлена ​​возможность объединять несколько объектов
  • Поддерживает глубокие объекты
  • параметр переопределения (обнаруживается, если последний параметр является логическим)

Если переопределение ложно, никакое свойство не переопределяется, но новые свойства будут добавлены.

Использование: obj.merge (объединяет ... [, переопределить]);

Вот мой код:

Object.defineProperty(Object.prototype, "merge", {
    enumerable: false,
    value: function () {
        var override = true,
            dest = this,
            len = arguments.length,
            props, merge, i, from;

        if (typeof(arguments[arguments.length - 1]) === "boolean") {
            override = arguments[arguments.length - 1];
            len = arguments.length - 1;
        }

        for (i = 0; i < len; i++) {
            from = arguments[i];
            if (from != null) {
                Object.getOwnPropertyNames(from).forEach(function (name) {
                    var descriptor;

                    // nesting
                    if ((typeof(dest[name]) === "object" || typeof(dest[name]) === "undefined")
                            && typeof(from[name]) === "object") {

                        // ensure proper types (Array rsp Object)
                        if (typeof(dest[name]) === "undefined") {
                            dest[name] = Array.isArray(from[name]) ? [] : {};
                        }
                        if (override) {
                            if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
                                dest[name] = [];
                            }
                            else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
                                dest[name] = {};
                            }
                        }
                        dest[name].merge(from[name], override);
                    } 

                    // flat properties
                    else if ((name in dest && override) || !(name in dest)) {
                        descriptor = Object.getOwnPropertyDescriptor(from, name);
                        if (descriptor.configurable) {
                            Object.defineProperty(dest, name, descriptor);
                        }
                    }
                });
            }
        }
        return this;
    }
});

Примеры и контрольные примеры:

function clone (obj) {
    return JSON.parse(JSON.stringify(obj));
}
var obj = {
    name : "trick",
    value : "value"
};

var mergeObj = {
    name : "truck",
    value2 : "value2"
};

var mergeObj2 = {
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
};

assertTrue("Standard", clone(obj).merge(mergeObj).equals({
    name : "truck",
    value : "value",
    value2 : "value2"
}));

assertTrue("Standard no Override", clone(obj).merge(mergeObj, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2"
}));

assertTrue("Multiple", clone(obj).merge(mergeObj, mergeObj2).equals({
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
}));

assertTrue("Multiple no Override", clone(obj).merge(mergeObj, mergeObj2, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2",
    value3 : "value3"
}));

var deep = {
    first : {
        name : "trick",
        val : "value"
    },
    second : {
        foo : "bar"
    }
};

var deepMerge = {
    first : {
        name : "track",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
};

assertTrue("Deep merges", clone(deep).merge(deepMerge).equals({
    first : {
        name : "track",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
}));

assertTrue("Deep merges no override", clone(deep).merge(deepMerge, false).equals({
    first : {
        name : "trick",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "bar",
        bar : "bam"
    },
    v : "on first layer"
}));

var obj1 = {a: 1, b: "hello"};
obj1.merge({c: 3});
assertTrue(obj1.equals({a: 1, b: "hello", c: 3}));

obj1.merge({a: 2, b: "mom", d: "new property"}, false);
assertTrue(obj1.equals({a: 1, b: "hello", c: 3, d: "new property"}));

var obj2 = {};
obj2.merge({a: 1}, {b: 2}, {a: 3});
assertTrue(obj2.equals({a: 3, b: 2}));

var a = [];
var b = [1, [2, 3], 4];
a.merge(b);
assertEquals(1, a[0]);
assertEquals([2, 3], a[1]);
assertEquals(4, a[2]);


var o1 = {};
var o2 = {a: 1, b: {c: 2}};
var o3 = {d: 3};
o1.merge(o2, o3);
assertTrue(o1.equals({a: 1, b: {c: 2}, d: 3}));
o1.b.c = 99;
assertTrue(o2.equals({a: 1, b: {c: 2}}));

// checking types with arrays and objects
var bo;
a = [];
bo = [1, {0:2, 1:3}, 4];
b = [1, [2, 3], 4];

a.merge(b);
assertTrue("Array stays Array?", Array.isArray(a[1]));

a = [];
a.merge(bo);
assertTrue("Object stays Object?", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo);
assertTrue("Object overrides Array", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo, false);
assertTrue("Object does not override Array", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b);
assertTrue("Array overrides Object", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b, false);
assertTrue("Array does not override Object", !Array.isArray(a[1]));

Мой метод equals можно найти здесь: Сравнение объектов в JavaScript

person Community    schedule 02.04.2011

В MooTools есть Object.merge ():

Object.merge(obj1, obj2);
person Community    schedule 31.07.2009

В Ext JS 4 это можно сделать следующим образом:

var mergedObject = Ext.Object.merge(object1, object2)

// Or shorter:
var mergedObject2 = Ext.merge(object1, object2)

См. слияние (объект) : Объект.

person Community    schedule 22.07.2011

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

// result
result: {food: "pizza", car: "ford", animal: "dog"}

Использование jQuery.extend () - Ссылка

// Merge obj1 & obj2 to result
var result1 = $.extend( {}, obj1, obj2 );

Использование _.merge () - Ссылка

// Merge obj1 & obj2 to result
var result2 = _.merge( {}, obj1, obj2 );

Использование _.extend () - Ссылка

// Merge obj1 & obj2 to result
var result3 = _.extend( {}, obj1, obj2 );

Использование Object.assign () ECMAScript 2015 (ES6) - Ссылка

// Merge obj1 & obj2 to result
var result4 = Object.assign( {}, obj1, obj2 );

Выход всех

obj1: { animal: 'dog' }
obj2: { food: 'pizza', car: 'ford' }
result1: {food: "pizza", car: "ford", animal: "dog"}
result2: {food: "pizza", car: "ford", animal: "dog"}
result3: {food: "pizza", car: "ford", animal: "dog"}
result4: {food: "pizza", car: "ford", animal: "dog"}
person Community    schedule 18.09.2018

На основе Маркуса и vsync 'answer , это расширенная версия. Функция принимает любое количество аргументов. Его можно использовать для установки свойств на узлах DOM и создания глубоких копий значений. Однако первый аргумент приводится по ссылке.

Для обнаружения узла DOM используется функция isDOMNode () (см. Вопрос о переполнении стека JavaScript isDOM - как проверить, есть ли Объект JavaScript - это объект DOM?)

Он был протестирован в Opera 11, Firefox 6, Internet Explorer 8 и Google Chrome 16.

Код

function mergeRecursive() {

  // _mergeRecursive does the actual job with two arguments.
  var _mergeRecursive = function (dst, src) {
    if (isDOMNode(src) || typeof src !== 'object' || src === null) {
      return dst;
    }

    for (var p in src) {
      if (!src.hasOwnProperty(p))
        continue;
      if (src[p] === undefined)
        continue;
      if ( typeof src[p] !== 'object' || src[p] === null) {
        dst[p] = src[p];
      } else if (typeof dst[p]!=='object' || dst[p] === null) {
        dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
      } else {
        _mergeRecursive(dst[p], src[p]);
      }
    }
    return dst;
  }

  // Loop through arguments and merge them into the first argument.
  var out = arguments[0];
  if (typeof out !== 'object' || out === null)
    return out;
  for (var i = 1, il = arguments.length; i < il; i++) {
    _mergeRecursive(out, arguments[i]);
  }
  return out;
}

Некоторые примеры

Установите innerHTML и стиль элемента HTML

mergeRecursive(
  document.getElementById('mydiv'),
  {style: {border: '5px solid green', color: 'red'}},
  {innerHTML: 'Hello world!'});

Объединяйте массивы и объекты. Обратите внимание, что undefined можно использовать для сохранения значений в левом массиве / объекте.

o = mergeRecursive({a:'a'}, [1,2,3], [undefined, null, [30,31]], {a:undefined, b:'b'});
// o = {0:1, 1:null, 2:[30,31], a:'a', b:'b'}

Любой аргумент, не относящийся к объекту JavaScript (включая null), будет проигнорирован. За исключением первого аргумента, также отбрасываются узлы DOM. Помните, что строки, созданные как new String (), на самом деле являются объектами.

o = mergeRecursive({a:'a'}, 1, true, null, undefined, [1,2,3], 'bc', new String('de'));
// o = {0:'d', 1:'e', 2:3, a:'a'}

Если вы хотите объединить два объекта в новый (не затрагивая ни один из двух), укажите {} в качестве первого аргумента

var a={}, b={b:'abc'}, c={c:'cde'}, o;
o = mergeRecursive(a, b, c);
// o===a is true, o===b is false, o===c is false

Изменить (автор: ReaperSoon):

Чтобы также объединить массивы

function mergeRecursive(obj1, obj2) {
  if (Array.isArray(obj2)) { return obj1.concat(obj2); }
  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = mergeRecursive(obj1[p], obj2[p]);
      } else if (Array.isArray(obj2[p])) {
        obj1[p] = obj1[p].concat(obj2[p]);
      } else {
        obj1[p] = obj2[p];
      }
    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];
    }
  }
  return obj1;
}
person Community    schedule 06.01.2012

Вам следует использовать defaultsDeep lodash

_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
// → { 'user': { 'name': 'barney', 'age': 36 } }
person Community    schedule 22.12.2015

С помощью Underscore.js для объединения массива объектов выполните:

var arrayOfObjects = [ {a:1}, {b:2, c:3}, {d:4} ];
_(arrayOfObjects).reduce(function(memo, o) { return _(memo).extend(o); });

Это приводит к:

Object {a: 1, b: 2, c: 3, d: 4}
person Community    schedule 15.03.2014

Стоит отметить, что версия из коллекции 140byt.es решает задачу на минимальном пространстве и стоит попробовать для этого:

Код:

function m(a,b,c){for(c in b)b.hasOwnProperty(c)&&((typeof a[c])[0]=='o'?m(a[c],b[c]):a[c]=b[c])}

Использование для ваших целей:

m(obj1,obj2);

Вот исходный Gist.

person Community    schedule 19.10.2012

ES2018 / TypeScript: многие ответы приемлемы, но я придумал более элегантное решение этой проблемы, когда вам нужно объединить два объекта без перезаписи перекрывающихся ключей объектов.

Моя функция также принимает неограниченное количество объектов для объединения в качестве аргументов функции:

(Здесь я использую нотацию TypeScript, не стесняйтесь удалять тип :object[] в аргументе функции, если вы используете простой JavaScript).

const merge = (...objects: object[]) => {
  return objects.reduce((prev, next) => {
    Object.keys(prev).forEach(key => {
      next[key] = { ...next[key], ...prev[key] }
    })
    return next
  })
}
person Community    schedule 14.03.2019
comment
Кажется, это не работает? typescript-play.js.org/#code/ - person Chris Stryczynski; 04.04.2019

Используйте оператор Spread, который следует за версией ES6

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
let result = {...obj1,...obj2};
console.log(result)

output { food: 'pizza', car: 'ford', animal: 'dog' }
person Community    schedule 11.01.2020

Похоже, это должно быть все, что вам нужно:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

var obj3 = { ...obj1, ...obj2 }

После этого obj3 должен иметь следующее значение:

{food: "pizza", car: "ford", animal: "dog"}

Попробуйте здесь:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

var obj3 = { ...obj1, ...obj2 }

console.log(obj3);

person Community    schedule 13.11.2019

Вы можете использовать Object.assign метод. Например:

var result = Object.assign(obj1, obj2);

Также обратите внимание, что он создает неглубокую копию объекта.

person Community    schedule 26.12.2019

Мой метод:

function mergeObjects(defaults, settings) {
    Object.keys(defaults).forEach(function(key_default) {
        if (typeof settings[key_default] == "undefined") {
            settings[key_default] = defaults[key_default];
        } else if (isObject(defaults[key_default]) && isObject(settings[key_default])) {
            mergeObjects(defaults[key_default], settings[key_default]);
        }
    });

    function isObject(object) {
        return Object.prototype.toString.call(object) === '[object Object]';
    }

    return settings;
}

:)

person Community    schedule 01.08.2013

Использовать:

//Takes any number of objects and returns one merged object
var objectMerge = function(){
    var out = {};
    if(!arguments.length)
        return out;
    for(var i=0; i<arguments.length; i++) {
        for(var key in arguments[i]){
            out[key] = arguments[i][key];
        }
    }
    return out;
}

Он был протестирован с:

console.log(objectMerge({a:1, b:2}, {a:2, c:4}));

Это приводит к:

{ a: 2, b: 2, c: 4 }
person Community    schedule 09.07.2011

gossi расширение метода Дэвида Коаллье:

Отметьте эти две строки:

from = arguments[i];
Object.getOwnPropertyNames(from).forEach(function (name) {

Нужно проверить "from" на нулевой объект ... Если, например, слияние объекта, полученного из Ответ Ajax, ранее созданный на сервере, свойство объекта может иметь значение" null ", и в этом случае приведенный выше код генерирует сообщение об ошибке:

"from" не является допустимым объектом

Так, например, добавление функции «... Object.getOwnPropertyNames (from) .forEach ...» в оболочку «if (from! = Null) {...}» предотвратит возникновение этой ошибки.

person Community    schedule 24.08.2011

Я использую следующее, написанное на чистом JavaScript. Он начинается с самого правого аргумента и объединяет их до первого аргумента. Возвращаемого значения нет, изменяется только первый аргумент, а самый левый параметр (кроме первого) имеет наибольший вес для свойств.

var merge = function() {
  var il = arguments.length;

  for (var i = il - 1; i > 0; --i) {
    for (var key in arguments[i]) {
      if (arguments[i].hasOwnProperty(key)) {
        arguments[0][key] = arguments[i][key];
      }
    }
  }
};
person Community    schedule 21.04.2015

неглубокий

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var merged = Object.assign({} , obj,obj2 ); //shallow merge 
obj2.address[0] = "new city"

result.address [0] изменен на "новый город", т.е. объединенный объект также изменится. Это проблема неглубокого слияния.

глубокий

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var result = Object.assign({} , JSON.parse(JSON.stringify(obj)),JSON.parse(JSON.stringify(obj2)) )

obj2.address[0] = "new city"

result.address [0] не изменяется

person Community    schedule 23.12.2019
comment
var merged = Object.assign ({}, obj, obj2) ничего не объединяет? - person GroovyDotCom; 16.11.2020

Я использовал Object.create (), чтобы сохранить настройки по умолчанию (используя __proto__ или Object.getPrototypeOf ()).

function myPlugin( settings ){
    var defaults = {
        "keyName": [ "string 1", "string 2" ]
    }
    var options = Object.create( defaults );
    for (var key in settings) { options[key] = settings[key]; }
}
myPlugin( { "keyName": ["string 3", "string 4" ] } );

Таким образом, я всегда могу позже выполнить «concat ()» или «push ()».

var newArray = options['keyName'].concat( options.__proto__['keyName'] );

Примечание. Перед объединением вам необходимо выполнить проверку hasOwnProperty, чтобы избежать дублирования.

person Community    schedule 04.12.2013

Вы можете объединять объекты, следуя моему методу

var obj1 = { food: 'pizza', car: 'ford' };
var obj2 = { animal: 'dog' };

var result = mergeObjects([obj1, obj2]);

console.log(result);
document.write("result: <pre>" + JSON.stringify(result, 0, 3) + "</pre>");

function mergeObjects(objectArray) {
    if (objectArray.length) {
        var b = "", i = -1;
        while (objectArray[++i]) {
            var str = JSON.stringify(objectArray[i]);
            b += str.slice(1, str.length - 1);
            if (objectArray[i + 1]) b += ",";
        }
        return JSON.parse("{" + b + "}");
    }
    return {};
}

person Community    schedule 14.10.2015

Правильная реализация в Prototype должна выглядеть так:

var obj1 = {food: 'pizza', car: 'ford'}
var obj2 = {animal: 'dog'}

obj1 = Object.extend(obj1, obj2);
person Community    schedule 13.03.2009

Я как бы начинаю работать с JavaScript, поправьте меня, если я ошибаюсь.

Но не лучше ли было бы объединить любое количество объектов? Вот как я это делаю, используя собственный объект Arguments.

Ключ к этому в том, что вы можете передать любое количество аргументов функции JavaScript, не определяя их в объявлении функции. Вы просто не можете получить к ним доступ без использования объекта Arguments.

function mergeObjects() (
    var tmpObj = {};

    for(var o in arguments) {
        for(var m in arguments[o]) {
            tmpObj[m] = arguments[o][m];
        }
    }
    return tmpObj;
}
person Community    schedule 01.07.2011

В YUI _ 1_ должен выполнить свою работу:

Y.merge(obj1, obj2, obj3....) 
person Community    schedule 08.02.2012

Для тех, кто использует Node.js, есть модуль NPM: node.extend

Установить:

npm install node.extend

Использование:

var extend = require('node.extend');
var destObject = extend(true, {}, sourceObject);
// Where sourceObject is the object whose properties will be copied into another.
person Community    schedule 08.04.2014
comment
Это не встроенная библиотека, это модуль NPM. - person ItalyPaleAle; 30.04.2014

ES5-совместимый родной однострочник:

var merged = [obj1, obj2].reduce(function(a, o) { for(k in o) a[k] = o[k]; return a; }, {})
person Community    schedule 24.04.2017

С помощью следующего помощника вы можете объединить два объекта в один новый объект:

function extend(obj, src) {
    for (var key in src) {
        if (src.hasOwnProperty(key)) obj[key] = src[key];
    }
    return obj;
}

// example
var a = { foo: true }, b = { bar: false };
var c = extend(a, b);

console.log(c);
// { foo: true, bar: false }

Обычно это полезно при объединении параметров dict с настройками по умолчанию в функции или плагине.

Если поддержка IE 8 не требуется, вы можете вместо этого использовать Object.keys для тех же функций:

function extend(obj, src) {
    Object.keys(src).forEach(function(key) { obj[key] = src[key]; });
    return obj;
}

Это требует немного меньше кода и немного быстрее.

person Community    schedule 07.11.2018

Слияние JSON-совместимых объектов JavaScript

Я рекомендую использовать неразрушающие методы, которые не изменяют исходный источник, Object.assign - это деструктивный метод, и он также не очень удобен для производства потому что он перестает работать в более ранних версиях браузеров, и у вас нет возможности исправить его с помощью альтернативы.

Слияние объектов JS всегда будет недосягаемым или неполным, независимо от решения. Но слияние совместимых объектов, совместимых с JSON, находится всего в одном шаге от возможности написать простой и переносимый фрагмент кода неразрушающего метода слияния серии объектов JS в возвращаемый мастер, содержащий все уникальные имена свойств и их соответствующие значения, синтезированные в единый мастер-объект по прямому назначению.

Принимая во внимание, что MSIE8 является первым браузером, добавившим встроенную поддержку объекта JSON, это большое облегчение, а повторное использование уже существующей технологии всегда приветствуется.

Ограничение вашего кода стандартными объектами, соответствующими JSON, является скорее преимуществом, чем ограничением, поскольку эти объекты также могут передаваться через Интернет. И, конечно же, для тех, кто хотел бы более глубокую обратную совместимость, всегда есть плагин json., Методы которого можно легко назначить переменной JSON во внешнем коде без необходимости изменять или переписывать используемый метод.

function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }

(Конечно, всегда можно дать ему более значимое имя, которое я еще не решил; вероятно, следует назвать его JSONmerge)

Вариант использования:

var master = Merge( obj1, obj2, obj3, ...objn );

Теперь, в отличие от Object.assign, это оставляет все объекты нетронутыми и в их исходном состоянии (в случае, если вы сделали что-то не так и вам нужно переупорядочить объединяемые объекты или иметь возможность использовать их отдельно для какой-либо другой операции перед повторным объединением).

Число аргументов слияния также ограничено только лимитом длины аргументов [который огромен]. Встроенная поддержка синтаксического анализа / строкового преобразования JSON уже оптимизирована для компьютера, что означает: он должен быть быстрее, чем любая скриптовая форма цикла JS. Итерация по заданным аргументам выполняется с использованием while - самого быстрого цикла в JS.

Не помешает кратко упомянуть тот факт, что мы уже знаем, что повторяющиеся свойства уникальных меток (ключей) объекта будут перезаписаны более поздним объектом, содержащим ту же метку ключа, что означает, что вы контролируете, какое свойство принимает на себя предыдущий, просто упорядочив или переупорядочив список аргументов. И преимущество получения чистого и обновленного мастер-объекта без дублирования в качестве окончательного результата.

;
var obj1 = {a:1}, obj2 = {b:2}, obj3 = {c:3}
;
function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }
;
var master = Merge( obj1, obj2, obj3 )
;
console.log( JSON.stringify( master ) )
;

person Community    schedule 20.04.2017

объединить два объекта с помощью Object.assign и оператора распространения.

Неправильный способ (изменить исходный объект из-за таргетинга o1)

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };
var merge = Object.assign(o1, o2, o3);
console.log(merge)  // {X:10, Y:20, Z:30}
console.log(o1)     // {X:10, Y:20, Z:30}

Верные пути

  • Object.assign ({}, o1, o2, o3) ==> таргетинг на новый объект

  • {... o1, ... o2, ... o3} ==> разлетающиеся объекты

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };

console.log('Does not modify original objects because target {}');
var merge = Object.assign({}, o1, o2, o3);
console.log(merge); // { X: 10, Y: 20, Z: 30 }
console.log(o1)

console.log('Does not modify original objects')
var spreadMerge = {...o1, ...o2, ...o3};
console.log(spreadMerge);
console.log(o1);

person Community    schedule 14.10.2019

Есть разные способы добиться этого:

Object.assign(targetObj, sourceObj);

targetObj = {...targetObj, ...sourceObj};
person Community    schedule 06.10.2020

Это объединяет obj в "значение по умолчанию" def. obj имеет приоритет для всего, что существует в обоих, поскольку obj копируется в def. Также обратите внимание, что это рекурсивно.

function mergeObjs(def, obj) {
    if (typeof obj == 'undefined') {
        return def;
    } else if (typeof def == 'undefined') {
        return obj;
    }
    for (var i in obj) {
        if (obj[i] != null && obj[i].constructor == Object) {
            def[i] = mergeObjs(def[i], obj[i]);
        } else {
            def[i] = obj[i];
        }
    }
    return def;
}

a = {x : {y : [123]}}
b = {x : {z : 123}}
console.log(mergeObjs(a, b));
// {x: {y : [123], z : 123}}
person Community    schedule 01.10.2012

A={a:1,b:function(){alert(9)}}
B={a:2,c:3}
A.merge = function(){for(var i in B){A[i]=B[i]}}
A.merge()

Результат: {a: 2, c: 3, b: function ()}

person Community    schedule 19.12.2012
comment
кстати, в dojo есть функция под названием mixin, поэтому dojo.mixin (A, B) сделает свое дело - person jleviaguirre; 19.12.2012

Это решение создает новый объект и может обрабатывать несколько объектов.

Кроме того, он рекурсивен, и вы можете выбрать погоду, которую вы хотите, чтобы перезаписать значения и объекты.

    function extendObjects() {

        var newObject        = {};
        var overwriteValues  = false;
        var overwriteObjects = false;

        for ( var indexArgument = 0; indexArgument < arguments.length; indexArgument++ ) {

            if ( typeof arguments[indexArgument] !== 'object' ) {

                if ( arguments[indexArgument] == 'overwriteValues_True' ) {

                    overwriteValues = true;            
                } else if ( arguments[indexArgument] == 'overwriteValues_False' ) {

                    overwriteValues = false;                             
                } else if ( arguments[indexArgument] == 'overwriteObjects_True' ) {

                    overwriteObjects = true;     
                } else if ( arguments[indexArgument] == 'overwriteObjects_False' ) {

                    overwriteObjects = false; 
                }

            } else {

                extendObject( arguments[indexArgument], newObject, overwriteValues, overwriteObjects );
            }

        }

        function extendObject( object, extendedObject, overwriteValues, overwriteObjects ) {

            for ( var indexObject in object ) {

                if ( typeof object[indexObject] === 'object' ) {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteObjects ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                    extendObject( object[indexObject], extendedObject[indexObject], overwriteValues, overwriteObjects );

                } else {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteValues ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                }

            }     

            return extendedObject;

        }

        return newObject;
    }

    var object1           = { a : 1, b : 2, testArr : [888, { innArr : 1 }, 777 ], data : { e : 12, c : { lol : 1 }, rofl : { O : 3 } } };
    var object2           = { a : 6, b : 9, data : { a : 17, b : 18, e : 13, rofl : { O : 99, copter : { mao : 1 } } }, hexa : { tetra : 66 } };
    var object3           = { f : 13, g : 666, a : 333, data : { c : { xD : 45 } }, testArr : [888, { innArr : 3 }, 555 ]  };

    var newExtendedObject = extendObjects( 'overwriteValues_False', 'overwriteObjects_False', object1, object2, object3 );

Содержание newExtendedObject:

{"a":1,"b":2,"testArr":[888,{"innArr":1},777],"data":{"e":12,"c":{"lol":1,"xD":45},"rofl":{"O":3,"copter":{"mao":1}},"a":17,"b":18},"hexa":{"tetra":66},"f":13,"g":666}

Скрипка: http://jsfiddle.net/o0gb2umb/

person Community    schedule 14.10.2014

Возможный способ добиться этого заключается в следующем.

if (!Object.prototype.merge){
    Object.prototype.merge = function(obj){
        var self = this;
        Object.keys(obj).forEach(function(key){
            self[key] = obj[key]
        });
    }
};

Я не знаю, лучше ли это, чем другие ответы. В этом методе вы добавляете merge function к Objects прототипу. Таким образом вы можете позвонить obj1.merge(obj2);

Примечание: вы должны проверить свой аргумент, чтобы увидеть, является ли он объектом, и «выбросить» правильный Error. В противном случае Object.keys выдаст 'ошибку'

person Community    schedule 30.12.2015

Вы можете назначить каждому объекту метод слияния по умолчанию (возможно, `` унаследовать '' лучшее имя):

Он должен работать либо с объектами, либо с конкретными функциями.

Приведенный ниже код обрабатывает переопределение объединенных значений, если это необходимо:

Object.prototype.merge = function(obj, override) {
// Don't override by default

    for (var key in obj) {
        var n = obj[key];
        var t = this[key];
        this[key] = (override && t) ? n : t;
    };

};

Данные испытаний ниже:

var Mammal = function () {
    this.eyes = 2;
    this.thinking_brain = false;
    this.say = function () {
    console.log('screaming like a mammal')};
}

var Human = function () {
    this.thinking_brain = true;
    this.say = function() {console.log('shouting like a human')};
}

john = new Human();

// Extend mammal, but do not override from mammal
john.merge(new Mammal());
john.say();

// Extend mammal and override from mammal
john.merge(new Mammal(), true);
john.say();
person Community    schedule 29.07.2013

Другой способ:

function concat_collection(obj1, obj2) {
    var i;
    var arr = new Array();

    var len1 = obj1.length;
    for (i=0; i<len1; i++) {
        arr.push(obj1[i]);
    }

    var len2 = obj2.length;
    for (i=0; i<len2; i++) {
        arr.push(obj2[i]);
    }

    return arr;
}

var ELEMENTS = concat_collection(A,B);
for(var i = 0; i < ELEMENTS.length; i++) {
    alert(ELEMENTS[i].value);
}
person Community    schedule 31.03.2015

Если вы используете Dojo Toolkit, то лучший способ объединить два объекта - использовать миксин.

Ниже приведен пример миксина Dojo Toolkit:

// Dojo 1.7+ (AMD)
require(["dojo/_base/lang"], function(lang){
  var a = { b:"c", d:"e" };
  lang.mixin(a, { d:"f", g:"h" });
  console.log(a); // b:c, d:f, g:h
});

// Dojo < 1.7
var a = { b:"c", d:"e" };
dojo.mixin(a, { d:"f", g:"h" });
console.log(a); // b:c, d:f, g:h

Для получения дополнительных сведений mixin.

person Community    schedule 26.09.2015

Вот что я использовал в своей кодовой базе для слияния.

function merge(to, from) {
  if (typeof to === 'object' && typeof from === 'object') {
    for (var pro in from) {
      if (from.hasOwnProperty(pro)) {
        to[pro] = from[pro];
      }
    }
  }
  else{
      throw "Merge function can apply only on object";
  }
}
person Community    schedule 11.01.2016

Мы можем создать пустой объект и объединить их for-loop:

var obj1 = {
  id: '1',
  name: 'name'
}

var obj2 = {
  c: 'c',
  d: 'd'
}

var obj3 = {}

for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }


console.log( obj1, obj2, obj3)

person Community    schedule 31.05.2018

Это можно сделать тремя способами:

Подход 1: -

// using spread ...
    let obj1 = {
        ...obj2
    };

Подход 2: -

// using  Object.assign() method
let obj1 = Object.assign({}, obj2);

Подход 3: -

// using JSON
let obj1 = JSON.parse(JSON.stringify(obj2));
person Community    schedule 11.02.2021

Попробуйте так, используя библиотеку jQuery

let obj1 = { food: 'pizza', car: 'ford' }
let obj2 = { animal: 'dog' }

console.log(jQuery.extend(obj1, obj2))
person Community    schedule 25.05.2021
comment
Вариант jquery уже описан здесь: stackoverflow.com/a/171455/4294399 - person Calculuswhiz; 25.05.2021

Если вам нужно глубокое слияние, которое также будет «объединять» массивы, объединяя их в результате, тогда эта функция ES6 может быть тем, что вам нужно:

function deepMerge(a, b) {
    // If neither is an object, return one of them:
    if (Object(a) !== a && Object(b) !== b) return b || a;
    // Replace remaining primitive by empty object/array
    if (Object(a) !== a) a = Array.isArray(b) ? [] : {};
    if (Object(b) !== b) b = Array.isArray(a) ? [] : {};
    // Treat arrays differently:
    if (Array.isArray(a) && Array.isArray(b)) {
        // Merging arrays is interpreted as concatenation of their deep clones:
        return [...a.map(v => deepMerge(v)), ...b.map(v => deepMerge(v))];
    } else {
        // Get the keys that exist in either object
        var keys = new Set([...Object.keys(a),...Object.keys(b)]);
        // Recurse and assign to new object
        return Object.assign({}, ...Array.from(keys,
            key => ({ [key]: deepMerge(a[key], b[key]) }) ));
    }
}

// Sample data for demo:
var a = {
    groups: [{
        group: [{
            name: 'John',
            age: 12
        },{
            name: 'Mary',
            age: 20
        }],
        groupName: 'Pair'
    }],
    config: {
        color: 'blue',
        range: 'far'
    }
};


var b = {
    groups: [{
        group: [{
            name: 'Bill',
            age: 15
        }],
        groupName: 'Loner'
    }],
    config: {
        range: 'close',
        strength: 'average'
    }
};

var merged = deepMerge(a, b);

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Обратите внимание, что если этой функции передается только один аргумент, она действует как функция глубокого клонирования.

person Community    schedule 31.12.2016

В EcmaScript2016 вы можете сделать следующее

Исправление: это предложение стадии 3, но оно всегда работало для меня.

const objA = {
  attrA: 'hello',
  attrB: true
}

const objB = {
  attrC: 2
}

const mergedObj = {...objA, ...objB}
person Community    schedule 02.02.2017
comment
Свойства распространения объекта не являются частью ES2016 - это предложение этапа 3. Кроме того, это уже было рассмотрено в этом ответе. - person Michał Perłakowski; 02.02.2017

person    schedule
comment
Это не сработает, если o2 содержит какие-либо свойства, которых еще нет в o1, именно поэтому у Маркуса есть команда try / catch, которую вы удалили. Ваш пример работает только потому, что все свойства o2 уже существуют в o1. Итак, это не слияние, и это не лучше! - person pancake; 24.04.2012
comment
нет, не терпит неудач, я только что успешно попробовал то, что вы сказали. - person vsync; 03.09.2013
comment
Следует отметить, что функция является деструктивной и obj1 , а также любые объекты, вложенные в нее, будут изменены, что может или не может быть тем, что вы хотели. Я переименовал функцию и аргументы в applyProperties(target, source) для ясности. - person mindplay.dk; 04.04.2016
comment
@ mindplay.dk - что значит деструктивный? суть в том, чтобы объединить o2 с o1, а не создавать новый (третий) объект o1, объединенный с o2. Я ответил на точный вопрос - person vsync; 04.04.2016
comment
@vsync деструктивен в том смысле, что, например, Array.sort () деструктивен, а Array.slice () - нет - это не критика, просто указание на факт :-) - person mindplay.dk; 09.04.2016
comment
@ mindplay.dk - в вопросе было явно предложено объединить один объект с другим, переопределив первый, поэтому очевидно, что это деструктивно по природе рассматриваемого вопроса. для неразрушающего ответа нужно перейти на страницу другого ответа - person vsync; 09.04.2016