객체 병합 (연관 배열)


147

JavaScript에서 두 개의 연관 배열을 병합하는 가장 좋은 / 표준 방법은 무엇입니까? 모두가 자신의 for루프 를 굴려서 그것을합니까 ?


10
자바 스크립트 btw에는 연관 배열이 없으며 객체 만 있습니다.
gblazex

Perl에서 같은 질문을
crossref

답변:


204

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/


편집 : 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 Operator를 사용하면됩니다 .

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

54
또는 obj1$.extend({}, obj1, obj2)
뭉침 현상

예, 참조로 전달 된 클로저 및 객체를 처리 할 때는 후속 작업을 위해 원래 객체에 영향을 미치지 않도록 rymo의 조언을 따르십시오.
Nathan Smith

2
최신 브라우저의 Object.assign()경우 라이브러리를 아직 사용하지 않는 경우 JQuery를 사용하지 않는 @manfred의 솔루션을 확인하십시오 .
Phil

작동하지만 첫 번째 매개 변수를 변경하므로 알아야 할 사항입니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
kulpae

62

이제 2016 년 가장 좋은 표준 방법은 Object.assign ()
Pure Javascript 라고 말합니다 . jQuery가 필요하지 않습니다.

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

자세한 정보, 예제 및 polyfill :
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


obj3의 유형은 무엇입니까? obj1이 IABC 유형 인 경우 obj3가 나중에 해당 유형을 유지합니까?
windmaomao

49

이것이 프로토 타입이하는 방식입니다 :

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);

편집 : 의견에서 bucabay가 올바르게 지적한 hasOwnProperty () 확인을 추가했습니다.


6
즉시 속성 만 복사하려면 테스트 소스 .hasOwnProperty (property)가 필요합니다. 그것이,이는 Object.prototype에에서 파생을 포함한 모든 속성을 복사합니다 수
bucabay

22

간단하게 ...

function mergeArray(array1,array2) {
  for(item in array1) {
    array2[item] = array1[item];
  }
  return array2;
}

6
arrau1.prototype
LeeGee

@LeeGee가 맞습니다. 그 hasOwnProperty수표 가 필요합니다 . 배열이 오해의 소지가있는 객체 (객체)를 참조하면 인수 이름은 array2가 변경되었거나 새 객체가 반환되어야 함을 전달해야합니다. 나는 대답을 편집 할 것이지만 실제로 는 이미 수정 된 Jonathan Fingland의 편집 된 답변 이 될 것 입니다.
Vaz

14

밑줄 에는 확장 방법이 있습니다.

소스 객체의 모든 속성을 대상 객체로 복사합니다. 순서가 다르므로 마지막 소스는 이전 인수에서 같은 이름의 속성을 재정의합니다.

_.extend(destination, *sources) 

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


6

이름은 같지만 값이 아닌 경우 속성을 덮어 쓰시겠습니까?

원래 객체 중 하나를 영구적으로 변경하고 싶습니까?

또는 새로운 병합 된 개체를 반환 하시겠습니까?

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];
            }
        }
    }
}

6

자신의 Extend / 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또는 다른 속성을. 이 방법은 그것에 관한 작은 책을 가지고있을 수 있으며 객체 병렬 처리가 필요하며 매우 복잡해질 수 있습니다. 요청에 따라 사용할 수있는 작은 라이브러리를 작성했습니다.

도움이 되었기를 바랍니다!


4
  1. 자바 스크립트에는 연관 배열 개념이 없으며 객체가 있습니다.
  2. 두 객체를 병합하는 유일한 방법은 속성을 반복하고 기본 유형이 아닌 값과 기본 유형의 값에 대한 포인터를 다른 인스턴스에 복사하는 것입니다.

8
Javascript의 객체는 연관 배열로 구현되므로 확실히 같은 개념이 있습니다
Dexygen

2

2019 년에는 두 가지 좋은 옵션이 있습니다.

객체 할당 [ doc ]

const result = Object.assign({}, baseObject, updatingObject);

물체 퍼짐 [ doc ]

const result = { ...baseObject, ...updatingObject};

첫 번째는 더 안전하고 표준적이고 다가 인 경향이 있습니다. 좋은 장단점 여기


1

Yahoo UI (YUI)에는 다음과 같은 도우미 기능도 있습니다.

http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html

YAHOO.namespace('example');

YAHOO.example.set1 = { foo : "foo" };
YAHOO.example.set2 = { foo : "BAR", bar : "bar" };
YAHOO.example.set3 = { foo : "FOO", baz : "BAZ" };

var Ye = YAHOO.example;

var merged = YAHOO.lang.merge(Ye.set1, Ye.set2, Ye.set3);

1

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);

0

심오한 객체 병합이 필요했습니다. 그래서 다른 모든 대답은별로 도움이되지 않았습니다. _.extend 및 jQuery.extend는 내가하는 것처럼 재귀 배열이 없으면 잘 작동합니다. 그러나 그렇게 나쁘지는 않습니다. 5 분 안에 프로그래밍 할 수 있습니다.

var deep_merge = function (arr1, arr2) {
    jQuery.each(arr2, function (index, element) {
        if (typeof arr1[index] === "object" && typeof element === "object") {
            arr1[index] = deep_merge(arr1[index], element);
        } else if (typeof arr1[index] === "array" && typeof element === "array") {
            arr1[index] = arr1[index].concat(element);
        } else {
            arr1[index] = element;
        }
    });
    return arr1;
}

0

jQuery에서 배열을 병합하려면 $ .merge는 어떻습니까?

var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';

0

재귀 솔루션 (객체 배열 확장) + null 확인

var addProps = function (original, props) {
    if(!props) {
        return original;
    }
    if (Array.isArray(original)) {
        original.map(function (e) {
            return addProps(e, props)
        });
        return original;
    }
    if (!original) {
        original = {};
    }
    for (var property in props) {
        if (props.hasOwnProperty(property)) {
            original[property] = props[property];
        }
    }
    return original;
};

테스트

console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));

[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }

Node JS와 함께 사용하려고 시도했지만 Object.getOwnPropertyNames is not a function앱이 중단됩니다.
Legoless

plv8 PostgreSQL 확장 내에서 오래된 v8 엔진과 함께 이것을 사용하고 있습니다. 그리고 그것은 브라우저에서 작동합니다. JS 엔진에서 "hasOwnProperty"와 동일한 기능을 수행하는 방법을 찾으십시오. 그런 다음이 논리를 재사용 할 수 있습니다.
sscarduzio

0

가장 좋은 해결책은 다음과 같습니다.

obj1.unshift.apply( obj1, obj2 );

또한 obj1문제없이 루프 안에서 자랄 수 있습니다. ( obj2동적 이라고 말하자 )

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.