keys - javascript object properties
Fusionar objetos(matrices asociativas) (15)
¿Cuál es la mejor forma / estándar de combinar dos matrices asociativas en JavaScript? ¿Todos lo hacen girando su propio bucle?
Rolling Your Own Extend / Mixin Function
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???'' });
...
Esto simplemente extiende un splat de objetos, recursivamente. Además, tenga en cuenta que esta función recursiva es TCO ( Tail-Call Optimized ) ya que su retorno es la última llamada a sí mismo.
Además, es posible que desee propiedades específicas . En este caso, es posible que desee condensar los objetos según el id
, la quantity
u otra propiedad. Este enfoque podría tener un pequeño libro escrito sobre él y requiere la yuxtaposición de objetos y puede ser muy complejo. He escrito una pequeña biblioteca para esto que está disponible a pedido.
¡Espero que esto ayude!
Solución recursiva (extiende también matrices de objetos) + nulo verificado
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;
};
Pruebas
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 }
- En Javascript no hay noción de matriz asociativa, hay objetos
- La única forma de fusionar dos objetos es recorrer sus propiedades y copiar punteros a sus valores que no son tipos primitivos y valores para tipos primitivos a otra instancia.
¿desea sobrescribir una propiedad si los nombres son los mismos pero los valores no?
Y quieres cambiar permanentemente uno de los objetos originales,
o quieres un nuevo objeto fusionado devuelto?
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];
}
}
}
}
Ahora, en 2016, diría que la mejor / estándar es Object.assign ()
Pure Javascript. No se necesita jQuery.
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2); // Object {a: 4, b: 2, c: 110}
Más información, ejemplos y polyfill aquí:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Aquí está la mejor solución.
obj1.unshift.apply( obj1, obj2 );
Además, obj1
puede crecer dentro de un bucle sin ningún problema. (digamos que obj2
es dinámico)
Así es como lo hace Prototype:
Object.extend = function(destination, source) {
for (var property in source) {
if (source.hasOwnProperty(property)) {
destination[property] = source[property];
}
}
return destination;
};
llamado como, por ejemplo:
var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };
var shortnames = Object.extend(arr1,arr2);
EDITAR : agregó hasOwnProperty () marcada como correctamente señalada por bucabay en los comentarios
En dojo , los 2-objetos / matrices "merge" serían lang.mixin(destination, source)
- también puedes mezclar múltiples fuentes en un destino, etc. - ver la referencia de la función mixin para más detalles.
Mantenlo simple...
function mergeArray(array1,array2) {
for(item in array1) {
array2[item] = array1[item];
}
return array2;
}
Necesitaba una fusión profunda de objetos. Entonces todas las otras respuestas no me ayudaron mucho. _.extend y jQuery.extend funcionan bien, a menos que tenga una matriz recursiva como yo. Pero no es tan malo, puedes programarlo en cinco minutos:
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;
}
Para combinar matrices en jQuery, ¿qué hay de $ .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'';
Yahoo UI (YUI) también tiene una función auxiliar para esto:
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);
con jquery puedes llamar $.extend
obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = $.extend(obj1, obj2);
obj1 == obj3 == {a: 4, b: 2, c: 110}
(assoc. matrices son objetos en js)
mira aquí: http://api.jquery.com/jQuery.extend/
editar: Como sugirió Rymo, es mejor hacerlo de esta manera:
obj3 = $.extend({}, obj1, obj2);
obj3 == {a: 4, b: 2, c: 110}
Como aquí obj1 (y obj2) permanecen sin cambios.
jquery tiene un booleano para una copia profunda. Podrías hacer algo como eso:
MergeRecursive = function(arr1, arr2){
$.extend(true, arr1, arr2);
return arr1;
};
También puede editar esta función para admitir n-arrays para fusionar.
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;
};
Entonces ahora puedes hacer
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);
Underscore también tiene un método extendido:
Copie todas las propiedades de los objetos de origen en el objeto de destino. Está en orden, por lo que la última fuente anulará las propiedades del mismo nombre en argumentos anteriores.
_.extend(destination, *sources)
_.extend({name : ''moe''}, {age : 50});
=> {name : ''moe'', age : 50}