En este artículo, hablaremos sobre el paso por valor y el paso por referencia en JavaScript.
JavaScript siempre pasa por valor, pero en una array u objeto, el valor es una referencia a él, por lo que puede «cambiar» los datos. JavaScript tiene 5 tipos de datos primitivos que se pasan por valor, son Boolean , NULL , undefined , String y Number . Tiene 3 tipos de datos no primitivos que se pasan por referencia, son Array , Function y Object. En tipos de datos no primitivos, tenemos algunos desafíos para copiar datos. Como sabemos, los objetos se crean en algún lugar de la memoria de la computadora. Cuando declaramos cualquier propiedad, crea un espacio en la memoria.
Ejemplo: la dirección es un tipo de datos que se pasa por valor al igual que un número, string y dirección apunta a la ubicación en la memoria.
Pasar por valor en caso de número.
<script> let age = 100; let age2 = age; document.write(age, age2); document.write("<br>"); age = 200; document.write(age, age2); </script>
Producción:
100 100 200 100
Pasar por valor en caso de string
<script> let name = 'sam'; let name2 = name; document.write(name, name2); document.write("<br>"); name = 'xyz'; document.write(name, name2); </script>
Producción:
sam sam xyz sam
Pase por referencia en caso de array
<script> const players = ['Sam', 'Sarah', 'Ryan', 'Poppy']; const team = players; document.write(players, team); </script>
Producción:
["Sam", "Sarah", "Ryan", "Poppy"] ["Sam", "Sarah", "Ryan", "Poppy"]
Ahora, si cambia los datos de la array de «equipo», también afecta a la array de «jugadores».
<script> const players = ['Sam', 'Sarah', 'Ryan', 'Poppy']; const team = players; team[3] = 'xyz'; document.write(players, team); </script>
Producción:
["Sam", "Sarah", "Ryan", "xyz"] ["Sam", "Sarah", "Ryan", "xyz"]
Es una referencia de array, no una copia de array. Ambos apuntan a la misma array.
Tenemos 4 formas de hacerlo. Al usar estos métodos, la array principal no cambiará.
- Usando el método slice():
<script>
const players = [
'Sam'
,
'Sarah'
,
'Ryan'
,
'Poppy'
];
const playersCopy = players.slice();
playersCopy[2]=
"west"
;
console.log(players, palyersCopy);
</script>
Producción:
["Sam", "Sarah", "Ryan", "Poppy"] ["Sam", "Sarah", "west", "Poppy"]
- Usando el método concat(): cree una nueva variable de array y luego concatene la anterior en la nueva array.
<script>
const players = [
'Sam'
,
'Sarah'
,
'Ryan'
,
'Poppy'
];
const playersCopy2 = [].concat(players);
playersCopy2[2]=
'hell'
;
document.write(players, playersCopy2);
</script>
Producción:
["Sam", "Sarah", "Ryan", "Poppy"] ["Sam", "Sarah", "hell", "Poppy"]
- Mediante el uso del operador de propagación ES6:
<script>
const players = [
'Sam'
,
'Sarah'
,
'Ryan'
,
'Poppy'
];
const playersCopy3 = [...players];
playersCopy3[3] =
'heeee hawww'
;
document.write(players, playersCopy3);
</script>
Producción:
["Sam", "Sarah", "Ryan", "Poppy"] ["Sam", "Sarah", "Ryan", "heeee hawww"]
- Usando Array.from():
<script>
const players = [
'Sam'
,
'Sarah'
,
'Ryan'
,
'Poppy'
];
const playersCopy4 = Array.from(players);
playersCopy4[3]=
"kim"
;
document.write(players, playersCopy4);
</script>
Producción:
["Sam", "Sarah", "Ryan", "Poppy"] ["Sam", "Sarah", "Ryan", "kim"]
Pasar por referencia en Objeto: Lo mismo ocurre con los objetos, también afecta al objeto original.
const person = { name: 'loren isum', age: 80 }; const captain = person; person.age = 25; console.log(captain, person);
Producción:
{name: "loren isum", age: 25} {name: "loren isum", age: 25}
Hay dos maneras de hacerlo.
- Usando el método de asignación():
<script>
const personObject = {
name:
'loren isum'
,
age: 80
};
const personCopy = Object.assign({},
personObject, { number: 99, age: 12 });
personCopy.age = 78;
console.log(personCopy, personObject);
</script>
Producción:
{name: "loren isum", age: 78, number: 99} {name: "loren isum", age: 80}
- Mediante el uso del operador Spread:
<script>
const personData = {
name:
'loren isum'
,
age: 80
};
const personCopy2 = {...personData };
personCopy2.age = 78;
console.log(personCopy2, personData );
</script>
Producción:
{name: "loren isum", age: 78} {name: "loren isum", age: 80}
Una cosa más que debe pensar sobre lo que sucederá en el caso de un operador igual e igualdad. Cuando usamos estos operadores en variables de tipo de referencia, verifican la referencia. Si la propiedad tiene una referencia al mismo elemento, la comparación dará como resultado «verdadero», de lo contrario, devolverá «falso».
<script> var arrayReference = ["Hi!"]; var arrayCopy = arrayReference; console.log(arrayCopy === arrayReference); </script>
Producción:
true
<script> var array1 = ['Hi!']; var array2 = ['Hi!']; console.log(array1 === array2); </script>
Producción:
false
Esto se puede corregir enstringndo la array.
<script> var arr1str = JSON.stringify(array1); var arr2str = JSON.stringify(array2); console.log(arr1str === arr2str); // true </script>
Producción:
true
Podemos cambiar la propiedad de nombre del objeto persona, pero no podemos restablecer la persona de referencia ya que se ha marcado como const.
<script> const person = { name: 'Tammy' }; // Name property changed person.name = 'abc'; // Objects are a reference type var val1 = { name: "Tom" }; var val2 = { name: "Tom" }; console.log(val1 == val2) </script>
Producción:
false
Pero podemos corregir esto enstringndo la array.
<script> var array1 = ['Hi!']; var array2 = ['Hi!']; var arr1str = JSON.stringify(array1); var arr2str = JSON.stringify(array2); console.log(arr1str === arr2str); </script>
Producción:
true
Pasar por referencia en caso de funciones: Si pasamos el objeto en la función, cambiará ambos objetos.
<script> function changevalue(person) { var newPersonObj = (person); newPersonObj.age = 25; return newPersonObj; } var alex = { name: 'xyz', age: 30 }; var alexChanged = changevalue(alex); console.log(alex); console.log(alexChanged); </script>
Producción:
{ name: 'xyz', age: 25 } { name: 'xyz', age: 25 }
Podemos resolver este problema analizando y enstringndo el objeto.
<script> function changevalue(person) { var newPersonObj = JSON.parse(JSON.stringify(person)); newPersonObj.age = 25; return newPersonObj; } var alex = { name: 'xyz', age: 30 }; var alexChanged = changevalue(alex); console.log(alex); console.log(alexChanged); </script>
Producción:
{ name: 'xyz', age: 30 } { name: 'xyz', age: 25 }