Объединение объектов (ассоциативные массивы) - PullRequest
145 голосов
/ 30 мая 2009

Какой лучший / стандартный способ объединения двух ассоциативных массивов в JavaScript? Все ли делают это, просто катая свой цикл for?

Ответы [ 16 ]

195 голосов
/ 06 июля 2010

с JQuery вы можете позвонить $.extend

var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};

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

obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS

(ассоциированные массивы - это объекты в js)

смотрите здесь: http://api.jquery.com/jQuery.extend/


edit: Как и предполагал rymo, лучше сделать это следующим образом:

obj3 = $.extend({}, obj1, obj2); 
obj3 == {a: 4, b: 2, c: 110}

Как и здесь, obj1 (и obj2) остаются без изменений.


edit2: В 2018 году это можно сделать с помощью Object.assign:

var obj3 = Object.assign({}, obj1, obj2); 
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS

При работе с ES6 этого можно достичь с помощью оператора Spread :

const obj3 = { ...obj1, ...obj2 };
58 голосов
/ 08 апреля 2016

Теперь в 2016 году я бы сказал, что лучший / стандартный способ - Object.assign ()
Чистый Javascript. JQuery не требуется.

obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2);  // Object {a: 4, b: 2, c: 110}

Больше информации, примеров и полифилла здесь:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

49 голосов
/ 30 мая 2009

Вот как это делает Prototype:

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

называется как, например:

var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };

var shortnames = Object.extend(arr1,arr2);

РЕДАКТИРОВАТЬ : добавлена ​​проверка hasOwnProperty (), правильно указанная bucabay в комментариях

22 голосов
/ 05 февраля 2012

Не усложняйте ...

function mergeArray(array1,array2) {
  for(item in array1) {
    array2[item] = array1[item];
  }
  return array2;
}
14 голосов
/ 17 декабря 2011

Подчеркивание также имеет метод расширения:

Скопируйте все свойства исходных объектов в целевой объект. Это в порядке, поэтому последний источник переопределит свойства с тем же именем в предыдущих аргументах.

_.extend(destination, *sources) 

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
7 голосов
/ 30 мая 2009

В dojo"объединение" двух объектов / массивов будет lang.mixin(destination, source) - вы также можете смешивать несколько источников в одном месте назначения и т. Д. - см. справочник по функции mixin для деталей.

6 голосов
/ 12 февраля 2015

Свертывание собственного Расширение / Mixin Функция

function extend(objects) {
    var args
        , first = Array.prototype.slice.call(arguments, 0, 1)[0]
        , second;

    if (arguments.length > 1) {
        second = Array.prototype.splice.call(arguments, 1, 1)[0];
        for (var key in second) {
            first[key] = second[key];
        }
        args = Array.prototype.slice.call(arguments, 0);
        return extend.apply(this, args);
    }

    return first;
}

...

var briansDirections = {
    step1: 'Remove pastry from wrapper.',
    step2: 'Place pastry toaster.',
    step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });

...

Это просто расширяет знак объектов, рекурсивно. Также обратите внимание, что эта рекурсивная функция имеет TCO ( Tail-Call Optimized ), поскольку ее возвращение является последним вызовом для себя.

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

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

6 голосов
/ 30 мая 2009

хотите ли вы перезаписать свойство, если имена совпадают, но значения не совпадают?

А хотите ли вы навсегда изменить один из исходных объектов,

или вы хотите вернуть новый объединенный объект?

function mergedObject(obj1, obj2, force){
    for(var p in obj1) this[p]= obj1[p];
    for(var p in obj2){
        if(obj2.hasOwnProperty(p)){
            if(force || this[p]=== undefined) this[p]= obj2[p];
            else{
                n= 2;
                while(this[p+n]!== undefined)++n;
                this[p+n]= obj2[p];
            }
        }
    }
}
4 голосов
/ 30 мая 2009
  1. В Javascript нет понятия ассоциативный массив, есть объекты
  2. Единственный способ объединить два объекта цикл для их свойств и копировать указатели на их значения, которые не являются примитивными типами и значениями для примитивных типов к другому Экземпляр
1 голос
/ 16 июля 2012

JQuery имеет логическое значение для глубокого копирования. Вы могли бы сделать что-то подобное:

MergeRecursive = function(arr1, arr2){
    $.extend(true, arr1, arr2);
    return arr1;                
};

Также вы можете редактировать эту функцию для поддержки объединения n-массивов.

ArrayMergeRecursive = function(){
     if(arguments.length < 2){
          throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
     }

    var arr1=arguments[0];
    for(var i=0; i<=arguments.length; i++ ){
        $.extend(true, arr1, arguments[i]);                 
    }

    return arr1;                
};

Так что теперь вы можете сделать

var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
    arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
    arr3 = ['Peter','Jhon','Demosthenes'],
    results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...