He escrito el siguiente JavaScript:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']
var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4
Este código declara una variable myArray
y la establece en un valor de matriz. Luego declara una segunda variable copyOfMyArray
y la establece en myArray
. Realiza una operación en copyOfMyArray
y luego alerta a ambos myArray
y copyOfMyArray
. De alguna manera, cuando realizo una operación en copyOfMyArray
, parece que se realiza la misma operación en myArray
.
Luego, el código hace lo mismo con un valor numérico: declara una variable myNumber
y la establece en un valor numérico. Luego declara una segunda variable copyOfMyNumber
y la establece en myNumber
. Realiza una operación en copyOfMyNumber
y luego alerta a ambos myNumber
y copyOfMyNumber
. Aquí, obtengo el comportamiento esperado: diferentes valores para myNumber
y copyOfMyNumber
.
¿Cuál es la diferencia entre una matriz y un número en JavaScript que parece que cambiar una matriz cambia el valor de una copia de la matriz, mientras que cambiar un número no cambia el valor de una copia del número?
Supongo que, por alguna razón, se hace referencia a la matriz por referencia y al número por valor, pero ¿por qué? ¿Cómo puedo saber qué comportamiento esperar con otros objetos?
fuente
myArray.slice(0);
directamente en ese contexto?Bueno, la única respuesta posible, y la correcta, es que en realidad no está copiando la matriz. Cuando escribes
var copyOfArray = array;
estás asignando una referencia a la misma matriz en otra variable. Ambos apuntan al mismo objeto, en otras palabras.
fuente
5
son siempre iguales.Entonces, todos aquí han hecho un gran trabajo al explicar por qué está sucediendo esto; solo quería escribir una línea y hacerle saber cómo pude solucionarlo, con bastante facilidad:
thingArray = ['first_thing', 'second_thing', 'third_thing'] function removeFirstThingAndPreserveArray(){ var copyOfThingArray = [...thingArray] copyOfThingArray.shift(); return copyOfThingArray; }
Esto está usando la sintaxis ... spread.
Propagar fuente de sintaxis
EDITAR: En cuanto al por qué de esto, y para responder a su pregunta:
La respuesta es que en JavaScript, las matrices y los objetos son mutables , mientras que las cadenas, los números y otras primitivas son inmutables . Cuando hacemos una tarea como:
copyOfMyArray es realmente solo una referencia a myArray, no una copia real.
Recomendaría este artículo, ¿Qué son las estructuras de datos inmutables y mutables? , para profundizar en el tema.
Glosario de MDN: Mutable
fuente
Clonación de objetos -
A
loop / array.push
produce un resultado similar aarray.slice(0)
oarray.clone()
. Todos los valores se pasan por referencia, pero dado que la mayoría de los tipos de datos primitivos son inmutables , las operaciones posteriores producen el resultado deseado: un 'clon'. Esto no es cierto para los objetos y matrices, por supuesto, que permiten la modificación de la referencia original (son tipos mutables).Tome el siguiente ejemplo:
const originalArray = [1, 'a', false, {foor: 'bar'}] const newArray = []; originalArray.forEach((v, i) => { newArray.push(originalArray[i]); }); newArray[0] = newArray[0] + 1; newArray[1] = 'b'; newArray[2] = true; newArray[3] = Object.assign(newArray[3], {bar: 'foo'});
Todas las operaciones que se ejecutan en los índices newArray producen el resultado deseado, excepto el (objeto) final, que, debido a que se copia por referencia, también mutará el originalArray [3].
https://jsfiddle.net/7ajz2m6w/
Tenga en cuenta que
array.slice(0)
and array.clone()
sufre de esta misma limitación.Una forma de resolver esto es clonando efectivamente el objeto durante la secuencia de inserción:
originalArray.forEach((v, i) => { const val = (typeof v === 'object') ? Object.assign({}, v) : v; newArray.push(val); });
https://jsfiddle.net/e5hmnjp0/
salud
fuente
En JS, el operador "=" copia el puntero al área de memoria de la matriz. Si desea copiar una matriz en otra, debe usar la función Clonar.
Para enteros es diferente porque son un tipo primitivo.
S.
fuente
Todo se copia por referencia, excepto los tipos de datos primitivos (cadenas y números IIRC).
fuente
No tienes copias.
Tiene varias variables que contienen la misma matriz.
Del mismo modo, tiene varias variables que contienen el mismo número.
Cuando escribe
copyOfMyNumber = ...
, está poniendo un nuevo número en la variable.Eso es como escribir
copyOfMyArray = ...
.Cuando escribe
copyOfMyArray.splice
, está modificando la matriz original .Eso no es posible con los números porque los números son inmutables y no se pueden modificar,
fuente
Cree un filtro de la matriz original en arrayCopy. De modo que los cambios en la nueva matriz no afectarán a la matriz original.
var myArray = ['a', 'b', 'c']; var arrayCopy = myArray.filter(function(f){return f;}) arrayCopy.splice(0, 1); alert(myArray); // alerts ['a','b','c'] alert(arrayCopy); // alerts ['b','c']
Espero eso ayude.
fuente
El problema con la copia superficial es que todos los objetos no se clonan, sino que obtienen una referencia, por lo que array.slice (0) funcionará bien solo con una matriz literal, pero no hará una copia superficial con una matriz de objetos. En ese caso, una forma es ...
var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}]; var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement)); console.log(clonedArray); // [{name: 'foo', id: 121}, {name: 'zoo', id: 321}] // shallow copy
fuente
Puede agregar un poco de manejo de errores según sus casos y usar algo similar a la siguiente función para resolver el problema. Por favor comente si hay errores / problemas / ideas de eficiencia.
function CopyAnArray (ari1) { var mxx4 = []; for (var i=0;i<ari1.length;i++) { var nads2 = []; for (var j=0;j<ari1[0].length;j++) { nads2.push(ari1[i][j]); } mxx4.push(nads2); } return mxx4; }
fuente
Una matriz o un objeto en javascript siempre tiene la misma referencia a menos que clone o copie. Aquí hay un ejemplo:
http://plnkr.co/edit/Bqvsiddke27w9nLwYhcl?p=preview
// for showing that objects in javascript shares the same reference var obj = { "name": "a" } var arr = []; //we push the same object arr.push(obj); arr.push(obj); //if we change the value for one object arr[0].name = "b"; //the other object also changes alert(arr[1].name);
Para la clonación de objetos, podemos usar .clone () en jquery y angular.copy (), estas funciones crearán un nuevo objeto con otra referencia. Si conoce más funciones para hacer eso, por favor dígame, ¡gracias!
fuente