Crea una cuenta o inicia sesi贸n

隆Contin煤a aprendiendo sin ning煤n costo! 脷nete y comienza a potenciar tu carrera

Mutable o Inmutable

3/28
Recursos

Los conceptos de mutabilidad e inmutabilidad son muy importantes para los siguientes m茅todos de arrays. Existen m茅todos mutables que cambian el array original; e inmutables que devuelven un array diferente al original.

Referencias en memoria

En JavaScript, cada estructura est谩 guardada en una referencia en memoria, por lo que si cambiamos un elemento en el array, tambi茅n lo haremos en esa referencia. Al clonar arrays, se crea un nuevo array que tiene las mismas referencias en memoria que el original, por lo que si se realiza un cambio en el original, tambi茅n cambiar谩 en la copia.

const original = [1,2,3]
const copia = original
copia[0] = "Hola"

console.log(original) // [ 'Hola', 2, 3 ]

Diferencia entre mutabilidad e inmutabilidad

Con lo mencionado anteriormente, mutable es aquella acci贸n que cambia el valor en la referencia en memoria del elemento del array original, provocando que cambien el original y la copia. Inmutable es la acci贸n en la que se cambia el valor, pero en una referencia diferente del original, provocando que el original siga igual.

La mutabilidad es m谩s flexible y una buena opci贸n si se requiere cambiar, actualizar o eliminar datos; pero esto puede ocasionar fallos o resultados err贸neos en nuestra aplicaci贸n. La inmutabilidad es m谩s exigente, te permite generar nuevas estructuras para manejarlas sin cambiar la original; pero esto puede provocar que la memoria colapse.

Por lo que, 驴cu谩l es mejor? La respuesta es ninguna, cada uno te permite manejar estructuras de datos, por ende es necesario identificar cu谩l forma es la adecuada a aplicar en un algoritmo.

Contribuci贸n creada por: Andr茅s Guano.

Aportes 25

Preguntas 2

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

No te quedo claro la clase lee esto.

En JS los datos asignados a una variable pueden ser de dos tipos:

Primitive type (undefined, null, boolean, number, string, symbol), Reference type (objects, arrays , functions).

Una de las diferencia entre estas dos, est谩 en la forma como se almacenan estos datos en memoria, para ser m谩s claro un ejemplo.

let name = 'Javier';

let name2 = name;

let person = {name: 'javier'};

let person2 = person;

Cuando creamos name js crea un espacio en memoria y guarda su valor, ahora cuando creamos name2 js contin煤a crea un nuevo espacio en memoria y asigna el mismo valor de la varible name de esta forma el valor de la variable name2 es totalmente independiente a name.

Ahora si creamos la variable person como un objeto que contiene un name, y si luego creamos otra variable person2 y le asignamos el mismo objeto person, aqu铆 es donde la cosa cambia con respectos a los datos primitivos, en este caso js guardara el objeto person2 como una referencia o apuntador al objeto person, es decir que ambas variables apuntan al mismo objeto en memoria.

Ahora si entendamos Mutable o Inmutable.

Mutable: es algo que se puede cambiar o agregar.

Inmutable: es algo que no puede cambiar ni agregar.

Los valores primitivos en js son algo agregado donde solo se pueden reasignar y por lo tanto, todos estos valores son inmutables. Entendamos con un ejemplo.

console.log(name); //javier
console.log(name2); //javier

name2 = 'platzi';

console.log(name); //javier
console.log(name2); //platzi''

Si imprimimos name y name2, ambas nos dan javier, pero si reasignamos un valor de name2 y volvemos a imprimir ocurre que solo cambia el valor de name2, lo que demuestra que js guardas est谩s variables de forma separada, aun cuando el valor de name2 se copio de name. Por eso los valores primitivos son inmutables.

ahora hagamos lo mismo con los objetos.

console.log(person); //{name: 'javier'}
console.log(person2); //{name: 'javier'}

person2.name = 'platzi';

console.log(person); //{name: 'platzi'}
console.log(person2); //{name: 'platzi'}

Al inicio obtenemos las mismas propiedades, ahora cambiemos una de las valores de las propiedades y veremos que js cambio el valor tanto de person y peron2, esto debido a que person2 se creo haciendo referencia al objeto person, con reference type js crea una referencia al mismo objeto y el objeto permanece mutable.

ya que el mismo objeto es mutable se puede cambiar o se pueden agregar nuevas propiedades al mismo objeto.

En es6 se creo un operador de propagaci贸n que permirte copias un objeto de forma segura sin hacer referencia al mismo objeto y ser铆a as铆.

let person2 = {...person}

Ahora vuelve a ver la clase y veras como todo es m谩s claro y entendible.

Recomiendo esta charla (en ingles) sobre este tema, super incre铆ble: https://www.youtube.com/watch?v=Wo0qiGPSV-s&ab_channel=JSConf
.
Son 30 minutos valiosos 馃槂

Paso por referencia vs Paso por valor

Por tipos, los primitivos se pasan por valor y los objetos por referencia

Ejemplo gr谩fico:

Mutable es un tipo de variable que se puede cambiar. En JavaScript, solo los objetos (objects) y las matrices (arrays) son mutables, no valores primitivos.

(Puedes hacer que el nombre de una variable apunte a un nuevo valor, pero el valor anterior todav铆a se mantiene en la memoria. De ah铆 la necesidad de la recolecci贸n de basura).

Un objeto mutable es un objeto cuyo estado puede modificarse despu茅s de su creaci贸n.

Los inmutables son los objetos cuyo estado no se puede cambiar una vez creado el objeto.

Las cadenas y los n煤meros son inmutables. Entendamos esto con un ejemplo:

var immutableString = 鈥淗ola鈥;

// En el c贸digo anterior, se crea un nuevo objeto con valor de cadena.

immutableString = immutableString + 鈥淢undo鈥;

// Ahora agregamos 鈥淢undo鈥 al valor existente.

Al agregar 鈥渋mmutableString鈥 con un valor de cadena, ocurren los siguientes eventos:

Se recupera el valor existente de "immutableString"
"World" se agrega al valor existente de "immutableString"
El valor resultante luego se asigna a un nuevo bloque de memoria
El objeto "immutableString" ahora apunta al espacio de memoria reci茅n creado
El espacio de memoria creado anteriormente ahora est谩 disponible para la recolecci贸n de basura.

Spread Operator

Utilizando el spread operator, cogemos los valores de person y los insertamos directamente en X. As铆 evitamos anidar un abjeto dentro de otro
Con el spread operator, podemos sumar arrays, hacer copias, a帽adir nuevos elementos鈥

Te das cuenta de que aprendes cuando comprendes las referencias en memoria de js 馃槂

Casi siempre es mejor clonar una lista en lugar de mutarla. Nos ayuda a evitar Side Effects.

Con las copias tenemos el mismo contenido pero distinta referencia en memoria.

// Reto clase
        const todo = [
            {name: "Comprar pan", status: true},
            {name: "Ir al gym", status: false},
            {name: "Terminar proyecto", status: false},
            {name: "Estudiar en Platzi", status: true},
        ];

        const list = document.getElementById('todo');

        todo.forEach((item) => {
            list.innerHTML += `
            <li>
                <label><input type="checkbox" ${item.status ? `checked` : ''}>${item.name}</label>
            </li>
            `
        })

Mutable: que muta, que puede cambiar.
inmutable: que no muta, que no cambia.

Primitive type: number, string, boolean, undefined, null
Reference type object, array , function

let array = [1,2,3,4,5,6]

array.metodo(funcion) // [2,4,6]

si vemos nuestro array original, podemos ver que ha mutado 鈥

console.log(array) // [2,4,6] 

esta bien si es lo que deseamos hacer, pero si quisi茅ramos evitar esto, podr铆amos copiar nuestro array original

let array = [1,2,3,4,5,6]
let copy = [...array]

console.log(array) // [1,2,3,4,5,6]
console.log(copy) // [1,2,3,4,5,6]

y modificar la copia

copy.metodo(funcion) // [2,4,6]

si miramos en consola, vemos que nuestro copia ha mutado, pero nuestro array original sigue igual

console.log(array) // [1,2,3,4,5,6]
console.log(copy) // [2,4,6]

esto podr铆a ser una soluci贸n, pero estar铆amos utilizando mas recursos en memoria y en ocasiones nuestro array original ser谩 un array muy grande y no es muy optimo realizar copias y abusar de los recursos de memoria.
podemos llamar un m茅todo sobre el array original y almacenar el resultado en una variable

let array = [1,2,3,4,5,6]
let arrayModificado = array.metodo(funcion)

si miramos en consola, podemos ver el nuevo array y nuestro array original igual

console.log(array) // [1,2,3,4,5,6]
console.log(arrayModificado) // [2,4,6]

pero que esta pasando aqui 鈥 驴no seria lo mismo que realizar una copia y mutar la copia?, 隆no!, es diferente.
si hacemos console.table(array) podemos ver el 铆ndice y los valores del array original

铆ndice - Valor 
0 - 1
1 - 2
2 - 3
3 - 4
4 - 5
5 - 6

lo que el m茅todo hace sobre el array original es realizar la funci贸n que le indiquemos, es este caso solo nos deja los indices que contengan elementos con n煤meros pares y los almacena dentro de la variable arrayModificado.
si hacemos console.table(arrayModificado)

铆ndice - Valor 
0 - 2
1 - 4
2 - 6

驴seguir铆a siendo lo mismo?,驴realizamos una copia y mutamos la copia?, no exactamente.
si es cierto que retornamos una nuevo array y lo almacenamos en una variable (arrayModificado), pero los valores almacenados dentro de sus indices est谩n haciendo referencia al array original.
una forma de verlo mas clara es como si tuvi茅ramos esto console.table(arrayModificado)

铆ndice - Valor 
0 - array[1]
1 - array[3]
2 - array[5]

si queremos comprobarlo, comparamos los valores y observamos que nos retorna true, esta haciendo referencia al mismo espacio en memoria

console.log(array[1] === arrayMofificado[0]) // true 
console.log(array[3] === arrayMofificado[1]) // true 
console.log(array[5] === arrayMofificado[2]) // true 

este nuevo array y sus valores en sus indices est谩n haciendo referencia al array original, de esta forma no estar铆amos mutando al array original ni realizando copias de el, desde el nuevo array estar铆amos haciendo referencia a los valores del array original y eliminando los indices que tengan n煤meros impares.
todas estas instrucciones que queremos que ejecute, las indicamos en el cuerpo de la funci贸n que pasamos por par谩metro al m茅todo.
.
.
podemos en un nuevo array hacer referencia a indices del array original y a帽adir o eliminar otros elementos, teniendo lo mejor de las formas anteriores, no copiando ni mutando el original, haciendo referencia al array original aprovechando mejor los recursos de la memoria y teniendo nuestro array original igual y un nuevo array con indices referenciados del array original.

En breves palabras. Si al ejecutar un m茅todo de manejo de arrays me retorna un nuevo array se aplica inmutabilidad, pero si al ejecutar un m茅todo de manejo de arrays y no retorna un array nuevo, sino que modifico el mismo array, se llama mutabilidad.

Si aun no les qued贸 claro este concepto, les recomiendo volver al curso Intermedio de Programaci贸n Orientada a Objetos y ver este video sobre Funcionamiento de Memoria en JavaScript. En resumen, los datos primitivos cuando se los copia, no hacen copias por referencia, mientras que las estructuras complejas, si hacen copias por referencia, por lo que puedes sin quieres afectar al mismo objeto. Si les interesa conocer mas a fondo como funciona esto, deberian tomar cursos de C y C++ ya que estos abordan t茅rminos como punteros y referencias.
Pero en resumen:

 class Person{
    constructor(name){
        this.name=name;
    }
}

let danny=new Person('danny');
let copy=danny; //danny apunta a copy y copy apunta a danny, cambiar valores en estos
//afecta al original y a la copia
//Cuando creo la copia y el original
console.log(danny);
console.log(copy);
//cambiar original
danny.name='juan';
console.log(copy);
//cambiar copia
copy.name='copia';
console.log(danny);

茅ste teacher es genial _

Eso de un 谩rbol y que solo cambia si algo cambio es el fundamento del Virtual DOM que usan React y Vue, por eso son tan r谩pidos. Angular utiliza el Incremental DOM, que esta basado en la memoria鈥

Recomiendo mucho este tutorial sobre el una peque帽isima intro al paradigma funcional y las funciones o metodos que ya nos provee el propio JS

https://www.youtube.com/watch?v=3eLx9syx8iI&t=948s

Caracter铆sticas de una funci贸n pura:

  • El valor que retorna depende s贸lo de los argumentos de entrada, es decir. El valor de retorno no cambiar谩 si los valores de entrada no cambian
  • No puede modificar nada que este fuera de su 谩mbito.

La copia es una referencia en memoria, solo copia los elementos cambiados, creando una nueva estructura de datos on referencias de memoria y nuevos elementos.

Cuando cambiamos el array original, hacemos una mutaci贸n(mutable) y cuando generamos un nuevo estado: Estamos creando una estructura de datos inmutable

Hay que entender esto. Si tienes una variable con un array a la cual ponemos array1, y otra variable array2 a la cual le asignamos el array1. Si cambiamos los valores de array2, estos cambios tambi茅n se veran reflejados en el array1 que es el array original, por que el array lo que guarda es una referencia en memoria.

let array1 = [1,2,3,4,5];
let array2 = array1;

array2.push(6)

console.log(array1) // [1,2,3,4,5,6]
console.log(array2) // [1,2,3,4,5,6]

Para crear un array que no este enlazado a la referencia del original hay varias maneras. La que me gusta usar es la funci贸n Array.from() de esta manera:

let array1 = [1,2,3,4,5];
let array2 = Array.from(array1); // [1,2,3,4,5]

array2.push(6);
console.log(array1) // [1,2,3,4,5]
console.log(array2) // [1,2,3,4,5,6]

De esta manera el nuevo array es una copia totalmente desligada de la referencia y ya no afectara al array original

Aqu铆 entra el concepto de shallow copy and deep copy
https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy

Tareas checkbox

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>For each</title>
</head>

<body>
  <div id="app"></div>
  <script>
    const tasks = [
      { task: 'ba帽arme', status: true },
      { task: 'curso arrays', status: false },
      { task: 'certificado eps', status: true },
      { task: 'limpiar', status: false }
    ]
    const app = document.getElementById('app')
    tasks.forEach(task => {
      app.innerHTML += `
        <div>
          <input type="checkbox" ${task.status && 'checked'}>${task.task}</input>  
        </div>
      `
    })
  </script>
</body>

</html>

De forma sencilla podemos entender los conceptos de Mutabilidad y Inmutabilidad como que 鈥

La Mutabilidad nos permite cambiar el tipo de dato de una variable, los objects y arrays son mutables.

y la Inmutabilidad no nos permite cambiar el tipo de dato de una variable, los valores primarios son inmutables.

Estaba buscando esta respuesta desde hace rato 鈥 por fin, esto es MUY importante, sino van a haber choques en la memoria y van a pasar cosas muy raras con los resultados al usar las variables o en este caso los arrays

Mutacion: El elemento original lo estamos cambiando
Inmutabilidad:Clonamos el elemento original y apartir de esta clonacion realizamos los cambios

Peque帽a ayuda:

Si realmente te importa entender todo lo que esta sucediendo, toma los 2 cursos de poo de platzi. Ahi entenderas mutabilidad, referencias, copias, inmutabilidad, y algormitos que te permitan generar copias reales y no referencias que sean un caos.

Para un mayor avance, toma el curso de introducion a los algoritmos. Debes saber lo que es hacer un bucle dentro de otro bucle y cuan costoso es eso.

Exitos!

este curso me parece muy necesario y buenisimo!!! hasta aqui van 5 stars!

En resumen, cuando utilizamos el mismo array sin modificaciones se llama MUTACI脫N.
Mientras que si copiamos o clonamos el array anterior con modificaciones, se le llama estructura de datos inmutable.
Para ser mas clara, aqu铆 tenemos un ejemplo visual:

//tenemos este array, como solo copiamos el array se le llama mutaci贸n:
let arrayOriginal = ['1',true,'pepe'];
let copia = arrayOriginal ;

//ahora en este caso usamos otro array pero modificandolo, ejemplo:
let array2 = ['luisa','fernando','pedro'];
let inmutacionArray = array2.push(9);
console.log('mutacion',copia); //en este, tenemos la mutacion(copia de array original)
console.log('inmutabildad',array2); //y en este, tenemos el array original(hablando de array2) mas una modificaci贸n(inmutabilidad)

PD : Te invito a probar este c贸digo para que sea mas entendible 馃槂

Agregamos despu茅s de la etiqueta li, el input de tipo (type) checkbox para marcar las tareas realizadas.

<div id="homeworks"></div>
    <script>
        const tareas = [
            {materia:"Matematicas", tarea:"Algebra pag 2"},
            {materia:"Quimica", tarea:"electrones"},
            {materia:"programacion", tarea:"usar foreach"},
            {materia:"dise帽o", tarea:"retoque foto"},
        ];

        let homeworks = document.getElementById("homeworks");
        tareas.forEach(item2 => {
            homeworks.innerHTML += `
            <li>${item2.tarea} - materia: ${item2.materia}</li><input type="checkbox">`;
        });
    </script>