2010-03-16 44 views
48

Estoy buscando la mejor manera de "agregar" múltiples objetos JavaScript (matrices asociativas).Cómo concatenar propiedades de varios objetos JavaScript

Por ejemplo, teniendo en cuenta:

a = { "one" : 1, "two" : 2 }; 
b = { "three" : 3 }; 
c = { "four" : 4, "five" : 5 }; 

¿cuál es la mejor manera de calcular:

{ "one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 } 
+3

Una nota semántica: a pesar de la sintaxis [], ellos no son matrices en absoluto. El orden no está realmente garantizado. –

+1

La orden de iteración no está garantizada por estándares ecma. Pero es la forma en que se implementa en la mayoría de los navegadores. (desde John Resig) Este comportamiento queda explícitamente sin definir por la especificación ECMAScript. En ECMA-262, sección 12.6.4: La mecánica de enumerar las propiedades ... depende de la implementación. Sin embargo, la especificación es bastante diferente de la implementación. Todas las implementaciones modernas de ECMAScript iteran a través de las propiedades de los objetos en el orden en que fueron definidas. Debido a esto, el equipo de Chrome ha considerado que esto es un error y lo solucionará. –

Respuesta

68

ECMAscript 6 introdujo Object.assign() para lograr esto de forma nativa en Javascript.

Objeto .El método assign() se usa para copiar los valores de todas las propiedades enumerables de uno o más objetos de origen a un objeto de destino. Devolverá el objeto de destino.

MDN documentation on 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 } 

Object.assign is supported in many modern browsers pero todavía no todos ellos. Utilice un transpiler como Babel y Traceur para generar JavaScript ES5 compatible con versiones anteriores.

+4

Este es uno de los mejores que pude decir. Como E6 ahora se usa principalmente, Object.assign es la mejor respuesta. –

+0

Si no sabe cuántos objetos deben combinarse, ya que están en una matriz, puede fusionarlos de la siguiente manera: 'Object.assign.apply ({}, [{a: 1}, {b: 2} , ....]) ' –

3
function Collect(a, b, c) { 
    for (property in b) 
     a[property] = b[property]; 

    for (property in c) 
     a[property] = c[property]; 

    return a; 
} 

Aviso: propiedades existentes en los objetos anteriores se sobrescribirán.

+2

Esto tiene el efecto secundario de 'a === d' al final. Eso podría estar bien y podría no ser así. – tvanfosson

29

Esto debe hacerlo:

function collect() { 
    var ret = {}; 
    var len = arguments.length; 
    for (var i=0; i<len; i++) { 
    for (p in arguments[i]) { 
     if (arguments[i].hasOwnProperty(p)) { 
     ret[p] = arguments[i][p]; 
     } 
    } 
    } 
    return ret; 
} 

de entrada:

a = { "one" : 1, "two" : 2 }; 
b = { "three" : 3 }; 
c = { "four" : 4, "five" : 5 }; 
d = collect(a, b, c); 
console.log(d); 

Salida:

Object one=1 two=2 three=3 four=4 five=5 
+0

¿'length' no busca el tamaño de la matriz en cada invocación? Estoy tan acostumbrado a escribir 'for (var i = 0, len = array.longitud; i tvanfosson

+1

Sí, eso es correcto. Es mejor rendimiento almacenar en caché la longitud una vez. Sin embargo, dado que el tamaño de los argumentos "matriz" probablemente nunca sea muy grande, en este caso no importará realmente. – jhurshman

+1

No, excepto ligeramente en IE6. El acceso a la propiedad de longitud cuesta lo mismo que acceder a la variable len. – Alsciende

33

jQuery tiene una buena manera de hacer esto.

http://api.jquery.com/jQuery.extend/

+0

+1 Incluso si no usa el método de jQuery, podría usar su código para ayudarlo a construir su propia implementación (tal vez más específica) – tvanfosson

+3

Y si no lo está t usando jQuery, usted * debería * ser. :) –

+12

@Randal: Hay muchas razones perfectamente buenas para no usar jQuery. –

0
function collect(a, b, c){ 
    var d = {}; 

    for(p in a){ 
     d[p] = a[p]; 
    } 
    for(p in b){ 
     d[p] = b[p]; 
    } 
    for(p in c){ 
     d[p] = c[p]; 
    } 

    return d; 
} 
2

¿Por qué la función se limita a 3 argumentos? Además, verifique hasOwnProperty.

function Collect() { 
    var o={}; 
    for(var i=0;i<arguments.length;i++) { 
     var arg=arguments[i]; 
     if(typeof arg != "object") continue; 
     for(var p in arg) { 
     if(arg.hasOwnProperty(p)) o[p] = arg[p]; 
     } 
    } 
    return o; 
} 
11

Underscore tiene algunos métodos para hacer esto;

1. _.extend(destination, *sources)

Copia todas las propiedades de la fuente objetos más a la destino objeto, y devolver el destino objeto.

_.extend(a, _.extend(b, c)); 
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 } 

O

_.extend(a, b); 
=> {"one" : 1, "two" : 2, "three" : 3} 
_.extend(a, c); 
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 } 

2. _.defaults(object, *defaults)

Rellene indefinidos propiedades en objeto con los valores de los valores por defecto objetos y devolver el objeto .

_.defaults(a, _.defaults(b, c)); 
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 } 

O

_.defaults(a, b); 
=> {"one" : 1, "two" : 2, "three" : 3} 
_.defaults(a, c); 
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 } 
+1

+ 1, ya estaba usando subrayado y me resultó útil. –

+1

respuesta genial, para todos b versiones de filas –

0

Probablemente, la forma más rápida, eficiente y más genérico es la siguiente (se puede combinar cualquier número de objetos e incluso copiar a la primera -> Asignar):

function object_merge(){ 
    for (var i=1; i<arguments.length; i++) 
     for (var a in arguments[i]) 
     arguments[0][a] = arguments[i][a]; 
    return arguments[0]; 
} 

También le permite modificar la primer objeto cuando pasa por referencia. Si no quiere esto pero quiere tener un objeto completamente nuevo que contenga todas las propiedades, puede pasar {} como primer argumento.

var object1={a:1,b:2}; 
var object2={c:3,d:4}; 
var object3={d:5,e:6}; 
var combined_object=object_merge(object1,object2,object3); 

combined_object y object1 ambos contienen las propiedades de object1, object2, object3.

var object1={a:1,b:2}; 
var object2={c:3,d:4}; 
var object3={d:5,e:6}; 
var combined_object=object_merge({},object1,object2,object3); 

En este caso, la combined_object contiene las propiedades de object1, object2, object3 pero object1 no se modifica.

Marque aquí: https://jsfiddle.net/ppwovxey/1/

Nota: los objetos de JavaScript se pasan por referencia.

0

también de escribir este object-merge componente reutilizable que también se basa en Object.assign fusionar varios objetos sin mutar ellos, y puede ser reutilizado sin duplicar

Ejemplo:

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

const obj = merge(o1, o2, o3); 
console.log(obj); // { a: 1, b: 2, c: 3 } 
console.log(o1); // { a: 1 } does not mutate objects 

(pruebas también añadidos).

6

ECMAScript 6 tiene spread operator. Y ahora usted puede hacer esto:

const obj1 = {1: 11, 2: 22} 
const obj2 = {3: 33, 4: 44} 
const obj3 = {...obj1, ...obj2} 
console.log(obj3) 

// {1: 11, 2: 22, 3: 33, 4: 44} 
0

más simple: los operadores de cálculo

var obj1 = {a: 1} 
var obj2 = {b: 2} 
var concat = { ...obj1, ...obj2 } // { a: 1, b: 2 } 
Cuestiones relacionadas