Объединить два объектных литерала в javascript

У меня есть два объектных литерала:

var animal = {
    eat: function() {
        console.log("eating...");
    }
}

var dog = {
    eat: "this has to be replaced when merged",
    nrOfLegs: 4
}

Вам нужна функция слияния:

dog = someMergingFunction(animal, dog);

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

{
    eat: function() {
        console.log("eating...");
    },
    nrOfLegs: 4
}

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

Как это сделать в Javascript?

Ответ 1

// usage merged = someMergingFunction(a, b, c, d, ...)
// keys in earlier args override keys in later args.
// someMergingFunction({foo:"bar"}, {foo:"baz"})
//  ==> {foo:"bar"}
function someMergingFunction () {
  var o = {}
  for (var i = arguments.length - 1; i >= 0; i --) {
    var s = arguments[i]
    for (var k in s) o[k] = s[k]
  }
  return o
}

Ответ 2

Следующее должно работать:

function merge(obj1, obj2) {
  var obj = {};

  for (var x in obj1)
    if (obj1.hasOwnProperty(x))
      obj[x] = obj1[x];

  for (var x in obj2)
    if (obj2.hasOwnProperty(x))
      obj[x] = obj2[x];

  return obj;
}

Если оба объекта имеют одно и то же свойство, значение в obj2 имеет приоритет.

Ответ 3

Я очень рекомендую метод расширения jQuery, так как он обеспечит полную поддержку браузера.

var object = $.extend({}, object1, object2, ..., objectN);

Помните, что первым аргументом является цель. Хорошим моментом в использовании расширения является то, что, следуя коду, вы можете сделать его рекурсивным:

var object = $.extend(object, object1, object2, ..., objectN);

Дополнительную информацию см. в документации jQuery: jQuery Docs for Extend

Ответ 4

Предположим, что свойства первого параметра переопределяют свойства второго параметра (в вашем примере):

function merge(obj1, obj2) {
    for(attr in obj1)
        obj2[attr]=obj1[attr];
    return obj2;
}

Ответ 5

Я рекомендую использовать underscore.js, поскольку он содержит функциональные возможности для этого и всю нагрузку связанных вещей:

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

http://underscorejs.org/#extend

Ответ 6

Это может привести к удалению мухи с помощью buick, но вам может быть интересно увидеть, как Dojo делает в основном то же самое в dojo.mixin (по крайней мере, если я правильно понял вопрос).

https://github.com/dojo/dojo/blob/0dddc5a0bfe3708e4ba829434602da51cbb041b7/_base/_loader/bootstrap.js#L277-366

Основная функциональность находится в dojo._mixin, а dojo.mixin заставляет ее работать итеративно для нескольких объектов постепенно за один снимок.

Обратите внимание, что dojo.mixin работает в противоположном направлении к тому, что вы намекали в своем примере.

Ответ 8

Здесь есть несколько хороших предложений.

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

Примечание: порядок приоритета определяется массивом. Каждый последующий объект будет перезаписывать идентичные свойства, если они существуют в предыдущих объектах. В противном случае новые свойства просто добавляются к одному возвращенному объекту.

Я надеюсь, что это поможет будущим посетителям в этом вопросе. Здесь функция очень короткая и сладкая:

var mergeObjects = function (objectsArray) {
    var result = {};
    for (var i = 0; i < objectsArray.length; i++) {
        for (var obj in objectsArray[i]) {
            if (objectsArray[i].hasOwnProperty(obj)) {
                result[obj] = objectsArray[i][obj];
            };
        };
    };
    return result;
};

Вы можете использовать его следующим образом:

// Define the mergeObjects function
var mergeObjects = function (objectsArray) {
  var result = {};
  for (var i = 0; i < objectsArray.length; i++) {
    for (var obj in objectsArray[i]) {
      if (objectsArray[i].hasOwnProperty(obj)) {
        result[obj] = objectsArray[i][obj];
      };
    };
  };
  return result;
};


// Define some objects to merge, keeping one property consistent so you can
// see it overwrite the old ones
var obj1 = { test1: "test", overwrite: "overwrite1" };
var obj2 = { test2: "test2", overwrite: "overwrite2" };
var obj3 = { test3: "test3", overwrite: "overwrite3" };

// Merge the objects
var newObject = mergeObjects([obj1, obj2, obj3]);

// Test the output
for (var obj in newObject){
  if (newObject.hasOwnProperty(obj)){
    document.body.innerHTML += newObject[obj] + "<br />";  
  }
}