lista - Copiando una matriz de objetos en otra matriz en javascript
lista de objetos javascript (7)
¿Cómo puedo copiar cada elemento de una matriz (donde los elementos son objetos) en otra matriz, para que sean totalmente independientes? No quiero cambiar un elemento de una matriz para que afecte a la otra.
Si la matriz de destino aún no existe ...
... puedes usar slice()
o concat()
. slice()
es probablemente más idiomático (también verá slice(0)
, pero el valor predeterminado es 0, así que ...):
var destinationArray = sourceArray.slice(); // Probably more idiomatic
// or
var destinationArray = sourceArray.concat();
A partir de ES2015 (también conocido como ES6), también hay Array.from
, que crea una nueva matriz a partir de cualquier cosa similar a una matriz (incluida una matriz real):
var destinationArray = Array.from(sourceArray);
( Array.from
puede ser shimmed / polyfilled para motores JavaScript más antiguos).
También a partir de ES2015, puede utilizar la notación de dispersión de matriz y una matriz literal con cualquier iterable (incluida una matriz real):
var destinationArray = [...sourceArray];
Después de eso, ambas matrices tendrán los mismos contenidos. Cambiar una matriz no cambiará la otra. Naturalmente, si una entrada de matriz es un objeto, la entrada para ese objeto en ambas matrices apuntará al mismo objeto; esta no es una copia "profunda".
Si la matriz de destino existe ...
... y desea agregar el contenido de la matriz fuente, puede usar push
:
destinationArray.push.apply(destinationArray, sourceArray);
Eso funciona llamando a push
en la matriz de destino utilizando la función de apply
funciones de JavaScript, que le permite especificar los argumentos para la llamada a la función como una matriz. push
empujará tantos elementos como argumentos tenga, por lo que termina copiando los elementos de la matriz de origen a la matriz de destino.
En ES2015 y posterior, puedes hacer ese limpiador con notación de propagación ( ...
):
destinationArray.push(...sourceArray);
Tenga en cuenta que en ambos casos, la llamada está limitada por el número máximo de argumentos funcionales del motor de JavaScript (al momento de escribir esto, al menos en miles para todos los motores principales [y no en cientos de miles, al menos no para el V8 de Chrome] ]).
Aquí hay una versión de ES5:
var source1, dest1, source2, dest2;
snippet.log("If dest doesn''t exist yet:");
source1 = [1, 2, 3, 4];
dest1 = source1.slice(0);
snippet.log("[before change] source1 = " + source1.join(", "));
snippet.log("[before change] dest1 = " + dest1.join(", "));
source1[2] = "three";
dest1[3] = "four";
snippet.log("[after change] source1 = " + source1.join(", "));
snippet.log("[after change] dest1 = " + dest1.join(", "));
snippet.log("If dest already exists and we''re just appending:");
source2 = [1, 2, 3, 4];
dest2 = [''a'', ''b'', ''c'', ''d''];
snippet.log("[before append] source2 = " + source2.join(", "));
snippet.log("[before append] dest2 = " + dest2.join(", "));
dest2.push.apply(dest2, source2);
snippet.log("[before change] source2 = " + source2.join(", "));
snippet.log("[before change] dest2 = " + dest2.join(", "));
source2[2] = "three";
dest2[7] = "four";
snippet.log("[after change] source2 = " + source2.join(", "));
snippet.log("[after change] dest2 = " + dest2.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Hay dos notas importantes.
- El uso de
array.concat()
no funciona con Angular 1.4.4 y jQuery 3.2.1 (este es mi entorno). - El
array.slice(0)
es un objeto. Entonces, si haces algo comonewArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0)
newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0)
, las dos nuevas matrices harán referencia a solo 1 matriz y el cambio de una afectará a la otra.
De forma alternativa, al utilizar newArray1 = JSON.parse(JSON.stringify(old array))
solo se copiará el valor, por lo que creará una nueva matriz cada vez.
Si quieres mantener la referencia:
Array.prototype.push.apply(destinationArray, sourceArray);
Sugiero usar concat()
si está usando nodeJS. En todos los demás casos, he encontrado que slice(0)
funciona bien.
Una excelente forma de clonar una matriz es con una matriz literal y el operador de dispersión . Esto es posible gracias a ES2015 .
let objArray = [{name:''first''}, {name:''second''}, {name:''third''}, {name:''fourth''}];
let clonedArr = [...objArray];
console.log(clonedArr) // [Object, Object, Object, Object]
Puede encontrar esta opción de copia en la documentación de MDN para operadores extendidos https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array
También es la mejor práctica de Airbnb . https://github.com/airbnb/javascript#es6-array-spreads
Nota : Normalmente, los operadores de difusión en ES2015 tienen un nivel de profundidad al copiar una matriz. Por lo tanto, no son adecuados para copiar matrices multidimensionales.
Una manera fácil de hacer que esto funcione es usar:
var cloneArray = JSON.parse(JSON.stringify(originalArray));
Tengo problemas para obtener arr.concat()
o arr.splice(0)
para obtener una copia profunda. El fragmento de arriba funciona perfectamente.
var clonedArray = array.concat();