Mutable e Inmutable en JavaScript

Mutable e Inmutable en JavaScript

Este artículo explica los conceptos de mutable e inmutable en JavaScript.

YouTube Video

Mutable e Inmutable en JavaScript

¿Qué es Mutable?

Mutable significa que un valor puede ser modificado. Los objetos y los arrays, que son tipos por referencia, son ejemplos típicos de estructuras de datos mutables.

Ejemplo de un Objeto Mutable

1let person = { name: "Alice", age: 25 };
2person.age = 26;
3console.log(person); // { name: "Alice", age: 26 }

En este código, la propiedad age del objeto person se cambia de 25 a 26. Dado que los objetos se pasan por referencia, el contenido en la dirección de memoria almacenada en la variable person se modifica.

Ejemplo de un Array Mutable

1let numbers = [1, 2, 3];
2numbers.push(4);
3console.log(numbers); // [1, 2, 3, 4]

En este código, se utiliza el método push para agregar un nuevo elemento 4 al array original. Esto modifica el array original, convirtiéndolo en una operación mutable.

Ejemplo en una Función

 1// Function to append a value to an array
 2function append(arr, value) {
 3    arr.push(value); // Modify the original array
 4    console.log(arr);
 5}
 6
 7let numbers = [1, 2, 3];
 8append(numbers, 4);
 9
10console.log(numbers); // [1, 2, 3, 4] (original array is modified)

Al realizar operaciones mutables dentro de una función, el array original también se modifica.

¿Qué es Inmutable?

Inmutable significa que un valor no puede ser modificado. Los tipos primitivos son fundamentalmente inmutables.

Ejemplo de un Tipo Primitivo Inmutable

1let str = "hello";
2str[0] = "H";
3console.log(str); // "hello"

Intentar cambiar el primer carácter de la cadena str a H falla porque las cadenas son inmutables.

Ejemplo en una Función

 1// Function to increment a number
 2function increment(num) {
 3    num++; // This modifies only the local copy of num
 4    console.log(num);
 5}
 6
 7let number = 10;
 8increment(number);
 9
10console.log(number); // 10 (original number remains unchanged)

Dado que los números son inmutables, las operaciones dentro de una función no afectan a la variable original.

Operaciones Inmutables en Arrays

Los arrays son mutables, pero crear un nuevo array en lugar de modificar el original permite realizar operaciones inmutables.

1// Create an array of numbers
2let numbers = [1, 2, 3];
3
4// Create a new array by spreading the original and adding a new element
5let newNumbers = [...numbers, 4];
6
7console.log(numbers); // [1, 2, 3] (original array is unchanged)
8console.log(newNumbers); // [1, 2, 3, 4] (new array with an added element)

Aquí, la sintaxis de propagación (...) se utiliza para crear un nuevo arreglo newNumbers. Dado que el arreglo original numbers no se modifica, esta es una operación inmutable.

Beneficios de usar estructuras de datos inmutables

Mejor previsibilidad

Dado que los datos inmutables no pueden ser modificados, es menos probable que ocurran cambios inesperados, lo que reduce el riesgo de errores.

Compatibilidad con bibliotecas basadas en inmutabilidad

Bibliotecas como React y Redux a menudo están diseñadas teniendo en cuenta los datos inmutables, lo que facilita la gestión del estado cuando se usan correctamente.

Hacer objetos inmutables con Object.freeze

Object.freeze se puede usar para prevenir modificaciones a un objeto.

1// Create a frozen object (properties cannot be modified)
2const person = Object.freeze({ name: "Alice", age: 25 });
3
4// Attempt to modify a property (ignored in non-strict mode, error in strict mode)
5person.age = 26;
6
7console.log(person); // { name: "Alice", age: 25 }

Sin embargo, Object.freeze realiza un congelamiento superficial, lo que significa que las propiedades de los objetos anidados siguen siendo mutables.

1// Create a frozen object with a nested object
2const user = Object.freeze({ profile: { name: "Bob" } });
3
4// Attempt to modify a nested property (this works because Object.freeze() is shallow)
5user.profile.name = "Charlie";
6
7console.log(user.profile.name); // "Charlie" (nested object is still mutable)

Para crear un objeto totalmente inmutable, se requiere un congelamiento profundo.

 1// Function to deeply freeze an object, making all nested objects immutable
 2function deepFreeze(obj) {
 3  Object.keys(obj).forEach(key => {
 4    if (typeof obj[key] === "object" && obj[key] !== null) {
 5      deepFreeze(obj[key]); // Recursively freeze nested objects
 6    }
 7  });
 8  return Object.freeze(obj); // Freeze the top-level object
 9}
10
11// Create a deeply frozen object
12const user = deepFreeze({ profile: { name: "Bob" } });
13
14// Attempt to modify a nested property (ignored)
15user.profile.name = "Charlie";
16
17console.log(user.profile.name); // "Bob" (unchanged due to deep freeze)

Resumen

  • Los datos mutables pueden ser modificados, incluidos objetos y arreglos.
  • Los datos inmutables no pueden ser modificados, incluidos los tipos primitivos como cadenas y números.
  • El uso de la sintaxis de propagación o map permite operaciones con datos inmutables..
  • Object.freeze y deepFreeze se pueden usar para prevenir modificaciones en objetos.
  • El uso de datos inmutables permite un código más predecible y menos propenso a errores.

El diseño inmutable mejora la seguridad y la legibilidad del código, ¡así que úsalo bien!

Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.

YouTube Video