significa react que porque mutabilidad inmutable inmutabilidad immutable from español javascript reactjs functional-programming immutability immutable.js

react - ¿Por qué la inmutabilidad es tan importante(o necesaria) en JavaScript?



porque string es inmutable (11)

¿Por qué la inmutabilidad es tan importante (o necesaria) en JavaScript?

La inmutabilidad se puede rastrear en diferentes contextos, pero lo más importante sería rastrearla contra el estado de la aplicación y contra la interfaz de usuario de la aplicación.

Consideraré el patrón JavaScript Redux como un enfoque muy moderno y moderno y porque lo mencionaste.

Para la interfaz de usuario, debemos hacerlo predecible . Será predecible si UI = f(application state) .

Las aplicaciones (en JavaScript) cambian el estado a través de acciones implementadas utilizando la función reductora .

La función reductora simplemente toma la acción y el estado anterior y devuelve el estado nuevo, manteniendo intacto el estado anterior.

new state = r(current state, action)

El beneficio es: viaja en el tiempo por los estados ya que se guardan todos los objetos de estado, y puedes renderizar la aplicación en cualquier estado ya que UI = f(state)

Para que pueda deshacer / rehacer fácilmente.

Sucede que la creación de todos estos estados aún puede ser eficiente en la memoria, una analogía con Git es excelente, y tenemos una analogía similar en el sistema operativo Linux con enlaces simbólicos (basados ​​en los inodos).

Actualmente estoy trabajando en los marcos React JS y React Native . En la mitad del camino me encontré con Immutability o la biblioteca Immutable-JS , cuando estaba leyendo sobre la implementación de Flux y Redux de Facebook.

La pregunta es, ¿por qué es tan importante la inmutabilidad? ¿Qué tiene de malo mutar objetos? ¿No hace las cosas simples?

Dando un ejemplo, consideremos una sencilla aplicación de lector de noticias con la pantalla de apertura como una vista de lista de titulares de noticias.

Si configuro decir una matriz de objetos con un valor inicialmente, no puedo manipularlo. Eso es lo que dice el principio de inmutabilidad, ¿verdad? (Corrígeme si me equivoco). Pero, ¿qué pasa si tengo un nuevo objeto de Noticias que tiene que actualizarse? En el caso habitual, podría haber agregado el objeto a la matriz. ¿Cómo lo logro en este caso? ¿Eliminar la tienda y recrearla? ¿Agregar un objeto a la matriz no es una operación menos costosa?


La pregunta es, ¿por qué es tan importante la inmutabilidad? ¿Qué tiene de malo mutar objetos? ¿No hace las cosas simples?

Sobre mutabilidad

Nada tiene de malo la mutabilidad desde el punto de vista técnico. Es rápido, está reutilizando la memoria. Los desarrolladores están acostumbrados desde el principio (como lo recuerdo). El problema existe en el uso de la mutabilidad y los problemas que este uso puede traer.

Si el objeto no se comparte con nada, por ejemplo, existe en el alcance de la función y no está expuesto al exterior, entonces es difícil ver beneficios en la inmutabilidad. Realmente en este caso no tiene sentido ser inmutable. La sensación de inmutabilidad comienza cuando algo se comparte.

Dolor de cabeza por mutabilidad

La estructura compartida mutable puede crear fácilmente muchas trampas. Cualquier cambio en cualquier parte del código con acceso a la referencia tiene impacto en otras partes con visibilidad de esta referencia. Tal impacto conecta todas las partes, incluso cuando no deben conocer los diferentes módulos. La mutación en una función puede bloquear una parte totalmente diferente de la aplicación. Tal cosa es un mal efecto secundario.

El siguiente problema a menudo con la mutación es el estado corrupto. El estado dañado puede ocurrir cuando el procedimiento de mutación falla en el medio, y algunos campos se modificaron y otros no.

Además, con la mutación es difícil rastrear el cambio. La verificación de referencia simple no mostrará la diferencia, para saber qué cambio se necesita hacer una verificación profunda. Además, para monitorear el cambio, es necesario introducir algunos patrones observables.

Finalmente, la mutación es la razón del déficit de confianza. Cómo puede estar seguro de que alguna estructura tiene valor deseado, si se puede mutar.

const car = { brand: ''Ferrari'' }; doSomething(car); console.log(car); // { brand: ''Fiat'' }

Como se muestra en el ejemplo anterior, pasar una estructura mutable siempre puede terminar teniendo una estructura diferente. La función doSomething está mutando el atributo dado desde afuera. No confías en el código, realmente no sabes lo que tienes y lo que tendrás. Todos estos problemas tienen lugar porque: Las estructuras mutables representan punteros a la memoria.

La inmutabilidad se trata de valores

La inmutabilidad significa que el cambio no se realiza en el mismo objeto, estructura, sino que el cambio se representa en uno nuevo. Y esto se debe a que la referencia representa el valor no solo el puntero de memoria. Cada cambio crea un nuevo valor y no toca el anterior. Tales reglas claras devuelven la confianza y la previsibilidad del código. Las funciones son seguras de usar porque, en lugar de la mutación, tratan con versiones propias con valores propios.

El uso de valores en lugar de contenedores de memoria da la certeza de que cada objeto representa un valor inmutable específico y es seguro usarlo.

Las estructuras inmutables representan valores.

Me estoy sumergiendo aún más en el tema en un artículo medio: https://medium.com/@macsikora/the-state-of-immutability-169d2cd11310


La pregunta es, ¿por qué es tan importante la inmutabilidad? ¿Qué tiene de malo mutar objetos? ¿No hace las cosas simples?

En realidad, lo contrario es cierto: la mutabilidad hace las cosas más complicadas, al menos a largo plazo. Sí, hace que su codificación inicial sea más fácil porque puede cambiar las cosas donde lo desee, pero cuando su programa aumenta, se convierte en un problema: si un valor cambió, ¿qué lo cambió?

Cuando hace que todo sea inmutable, significa que los datos ya no se pueden cambiar por sorpresa. Usted sabe con certeza que si pasa un valor a una función, no se puede cambiar en esa función.

En pocas palabras: si usa valores inmutables, es muy fácil razonar sobre su código: todos obtienen una copia única * de sus datos, por lo que no pueden confundirse y romper otras partes de su código. ¡Imagínese lo fácil que es trabajar en un entorno de subprocesos múltiples!

Nota 1: Existe un costo potencial de rendimiento para la inmutabilidad dependiendo de lo que esté haciendo, pero cosas como Immutable.js se optimizan lo mejor que pueden.

Nota 2: en el improbable caso de que no estuvieras seguro, Immutable.js y ES6 const significan cosas muy diferentes.

En el caso habitual, podría haber agregado el objeto a la matriz. ¿Cómo lo logro en este caso? ¿Eliminar la tienda y recrearla? ¿Agregar un objeto a la matriz no es una operación menos costosa? PD: Si el ejemplo no es la forma correcta de explicar la inmutabilidad, hágame saber cuál es el ejemplo práctico correcto.

Sí, su ejemplo de noticias es perfectamente bueno, y su razonamiento es exactamente correcto: no puede simplemente modificar su lista existente, por lo que debe crear una nueva:

var originalItems = Immutable.List.of(1, 2, 3); var newItems = originalItems.push(4, 5, 6);


Una toma diferente ...

Mi otra respuesta aborda la pregunta desde un punto de vista muy práctico, y todavía me gusta. Decidí agregar esto como otra respuesta en lugar de una adición a esa porque es una diatriba filosófica aburrida que con suerte también responde a la pregunta, pero que realmente no encaja con mi respuesta existente.

TL; DR

Incluso en proyectos pequeños, la inmutabilidad puede ser útil, pero no asuma que, porque existe, es para usted.

Respuesta mucho, mucho más larga

NOTA: para el propósito de esta respuesta, estoy usando la palabra ''disciplina'' para significar abnegación para algún beneficio.

Esto es similar en forma a otra pregunta: "¿Debo usar Typecript? ¿Por qué los tipos son tan importantes en JavaScript?". Tiene una respuesta similar también. Considere el siguiente escenario:

Usted es el único autor y mantenedor de una base de código JavaScript / CSS / HTML de unas 5000 líneas. Su jefe semi-técnico lee algo sobre el Calor mecanografiado como nuevo y sugiere que tal vez queramos pasar a él, pero le deja la decisión a usted. Entonces lees sobre eso, juegas con él, etc.

Entonces, ahora que tiene que hacer una elección, ¿pasa a Typecript?

El mecanografiado tiene algunas ventajas convincentes: inteligencia, detección temprana de errores, especificación de sus API por adelantado, facilidad para arreglar las cosas cuando la refactorización las rompe, menos pruebas. El mecanografiado también tiene algunos costos: ciertos modismos de JavaScript muy naturales y correctos pueden ser difíciles de modelar en su sistema de tipos no especialmente poderoso, las anotaciones aumentan la LoC, el tiempo y el esfuerzo de reescribir la base de código existente, un paso adicional en la tubería de compilación, etc. Más fundamentalmente, crea un subconjunto de posibles programas de JavaScript correctos a cambio de la promesa de que es más probable que su código sea correcto. Es arbitrariamente restrictivo. Ese es el punto: impones una disciplina que te limita (con suerte de dispararte en el pie).

Volviendo a la pregunta, reformulada en el contexto del párrafo anterior: ¿ vale la pena ?

En el escenario descrito, afirmaría que si está muy familiarizado con una base de código JS de pequeña a mediana, la elección de utilizar Typecript es más estética que práctica. Y está bien , no hay nada de malo en la estética, simplemente no son necesariamente convincentes.

Escenario B:

Cambias de trabajo y ahora eres un programador de línea de negocios en Foo Corp. Estás trabajando con un equipo de 10 personas en una base de código JavaScript / HTML / CSS 90000 LoC (y contando) con una tubería de compilación bastante complicada que involucra babel, paquete web , un conjunto de polyfills, reaccionan con varios complementos, un sistema de gestión de estado, ~ 20 bibliotecas de terceros, ~ 10 bibliotecas internas, complementos de editor como un linter con reglas para la guía de estilo interna, etc.

Cuando eras 5k LoC chico / chica, simplemente no importaba mucho. Incluso la documentación no era un gran problema, incluso volviendo a una parte particular del código después de 6 meses, podría resolverlo con bastante facilidad. Pero ahora la disciplina no solo es agradable sino necesaria . Es posible que esa disciplina no implique el Script mecanografiado, pero es probable que implique alguna forma de análisis estático, así como todas las demás formas de disciplina de codificación (documentación, guía de estilo, scripts de construcción, pruebas de regresión, IC). La disciplina ya no es un lujo , es una necesidad .

Todo esto se aplicó a GOTO en 1978: su pequeño juego de blackjack en C podría usar GOTO sy la lógica de espagueti y simplemente no era tan importante elegir su propia aventura a través de él, pero a medida que los programas llegaron más grande y más ambicioso, bueno, el uso indisciplinado de GOTO no podría ser sostenido. Y todo esto se aplica a la inmutabilidad hoy.

Al igual que los tipos estáticos, si no está trabajando en una base de código grande con un equipo de ingenieros que la mantiene / extiende, la opción de usar la inmutabilidad es más estética que práctica: sus beneficios aún existen, pero es posible que aún no superen los costos.

Pero como con todas las disciplinas útiles, llega un punto en el que ya no es opcional. Si quiero mantener un peso saludable, entonces la disciplina con helado puede ser opcional. Pero si quiero ser un atleta competitivo, mi elección de comer o no helado está subsumida por mi elección de objetivos. Si desea cambiar el mundo con software, la inmutabilidad podría ser parte de lo que necesita para evitar que se colapse por su propio peso.


Una visión contraria de la inmutabilidad

Respuesta corta: la inmutabilidad es más una tendencia de moda que una necesidad en JavaScript. Hay algunos casos estrechos cuando se vuelve útil (React / Redux en su mayoría), aunque generalmente por razones equivocadas.

Respuesta larga: lea a continuación.

¿Por qué la inmutabilidad es tan importante (o necesaria) en JavaScript?

¡Bien, me alegra que lo hayas preguntado!

Hace algún tiempo, un tipo muy talentoso llamado Dan Abramov escribió una biblioteca de administración de estado de JavaScript llamada Redux que usa funciones puras e inmutabilidad. También hizo algunos videos realmente geniales que hicieron que la idea fuera realmente fácil de entender (y vender).

El momento fue perfecto. La novedad de Angular estaba desvaneciendo, y el mundo de JavaScript estaba listo para obsesionarse con lo último que tenía el grado correcto de genialidad, y esta biblioteca no solo era innovadora sino que encajaba perfectamente con React que estaba siendo promovida por otra potencia de Silicon Valley .

Triste como puede ser, las modas gobiernan en el mundo de JavaScript. Ahora Abramov está siendo aclamado como un semidiós y todos nosotros, simples mortales, tenemos que someternos al Dao de la Inmutabilidad ... Ya sea que tenga sentido o no.

¿Qué tiene de malo mutar objetos?

¡Nada!

De hecho, los programadores han estado mutando objetos durante er ... siempre que haya objetos para mutar. Más de 50 años de desarrollo de aplicaciones en otras palabras.

¿Y por qué complicar las cosas? Cuando tienes un objeto cat y muere, ¿realmente necesitas un segundo cat para seguir el cambio? La mayoría de la gente solo diría cat.isDead = true y se cat.isDead = true .

¿No hace (objetos mutantes) que las cosas sean simples?

¡SI! .. ¡Claro que lo hace!

Especialmente en JavaScript, que en la práctica es más útil para representar una vista de algún estado que se mantiene en otro lugar (como en una base de datos).

¿Qué sucede si tengo un nuevo objeto de Noticias que debe actualizarse? ... ¿Cómo lo logro en este caso? ¿Eliminar la tienda y recrearla? ¿Agregar un objeto a la matriz no es una operación menos costosa?

Bueno, puede seguir el enfoque tradicional y actualizar el objeto News , para que su representación en memoria de ese objeto cambie (y la vista que se muestra al usuario, o eso es lo que uno esperaría) ...

O alternativamente...

Puede probar el enfoque atractivo de FP / Inmutabilidad y agregar sus cambios al objeto News a una matriz que rastrea cada cambio histórico para que luego pueda iterar a través de la matriz y descubrir cuál debería ser la representación de estado correcta (¡uf!).

Estoy tratando de aprender lo que está justo aquí. Por favor, ilumíneme :)

Las modas van y vienen, amigo. Hay muchas formas de despellejar a un gato.

Lamento que tenga que soportar la confusión de un conjunto de paradigmas de programación en constante cambio. Pero bueno, BIENVENIDOS AL CLUB !!

Ahora hay un par de puntos importantes para recordar con respecto a la Inmutabilidad, y te los arrojará con la intensidad febril que solo la ingenuidad puede reunir.

1) La inmutabilidad es increíble para evitar las condiciones de carrera en entornos de subprocesos múltiples .

Los entornos de subprocesos múltiples (como C ++, Java y C #) son culpables de la práctica de bloquear objetos cuando más de un subproceso quiere cambiarlos. Esto es malo para el rendimiento, pero mejor que la alternativa de corrupción de datos. Y sin embargo, no es tan bueno como hacer que todo sea inmutable (¡Alabado sea Haskell!).

¡PERO AY! En JavaScript siempre operas en un solo hilo . Incluso los trabajadores web (cada uno se ejecuta dentro de un contexto separado ). Entonces, dado que no puede tener una condición de carrera relacionada con el hilo dentro de su contexto de ejecución (todas esas encantadoras variables globales y cierres), el punto principal a favor de la Inmutabilidad desaparece.

(Dicho esto, existe una ventaja de usar funciones puras en los trabajadores web, que es que no tendrás expectativas sobre jugar con objetos en el hilo principal).

2) La inmutabilidad puede (de alguna manera) evitar las condiciones de carrera en el estado de su aplicación.

Y aquí está el verdadero meollo del asunto, la mayoría de los desarrolladores (React) le dirán que la Inmutabilidad y la FP pueden de alguna manera hacer funcionar esta magia que permite que el estado de su aplicación sea predecible.

Por supuesto, esto no significa que pueda evitar las condiciones de carrera en la base de datos , para lograrlo tendría que coordinar a todos los usuarios en todos los navegadores , y para eso necesitaría una tecnología push de back-end como WebSockets ( más sobre esto a continuación) que transmitirá los cambios a todos los que ejecuten la aplicación.

Esta afirmación bastante confusa simplemente significa que los últimos valores asignados a un objeto de estado (definido por un solo usuario que opera dentro de su navegador) se vuelven predecibles. Lo que realmente no es ningún progreso en absoluto. Debido a que podría haber utilizado una variable mutada antigua para rastrear su estado y sabría que está tratando con la información más reciente cada vez que accede a ella, y esto funcionará con cualquier cosa menos React / Redux.

¿Por qué? Debido a que React es especial ... y el estado de los componentes se administra a través de una cadena de eventos sobre los que no tiene control y depende de que recuerde no mutar el estado directamente . Esto se ha manejado asombrosamente desde una perspectiva de relaciones públicas, ya que la exageración de React ha convertido una deficiencia en una moda sexy. Dejando de lado la moda, prefiero ver la inmutabilidad de lo que es, es decir, una herramienta para cerrar una brecha cuando su elección de marco no maneja el estado de forma intuitiva.

3) Las condiciones de carrera son categóricamente malas.

Bueno, podrían ser si estás usando React. Pero son raros si elige un marco diferente.

Además, normalmente tienes problemas mucho más grandes con los que lidiar ... Problemas como el infierno de la dependencia. Como una base de código hinchada. Como si tu CSS no se cargara. Como un proceso de construcción lento o estar atascado en un back-end monolítico que hace que la iteración sea casi imposible. Al igual que los desarrolladores sin experiencia que no entienden lo que está sucediendo y hacen un desastre.

Ya sabes. Realidad. Pero oye, ¿a quién le importa eso?

4) La inmutabilidad utiliza los Tipos de referencia para reducir el impacto en el rendimiento del seguimiento de cada cambio de estado.

Porque en serio, si vas a copiar cosas cada vez que cambia tu estado, es mejor que te asegures de ser inteligente al respecto.

5) La inmutabilidad le permite deshacer cosas .

Porque er ... esta es la característica número uno que su gerente de proyecto va a pedir, ¿verdad?

6) El estado inmutable tiene un gran potencial en combinación con WebSockets

Por último, pero no menos importante, la acumulación de deltas de estado es un caso bastante convincente en combinación con WebSockets, lo que permite un consumo fácil de estado como un flujo de eventos inmutables ...

Una vez que el centavo cae sobre este concepto (el estado es un flujo de eventos , en lugar de un conjunto crudo de registros que representan la última vista), el mundo inmutable se convierte en un lugar mágico para habitar. Una tierra de maravillas y posibilidades event-sourced de event-sourced que trasciende el tiempo mismo . Y cuando se hace correctamente, esto definitivamente puede hacer que las aplicaciones en tiempo real sean más fáciles de lograr, solo se transmite el flujo de eventos a todos los interesados ​​para que puedan construir su propia representación del presente y escribir sus propios cambios en el flujo comunitario.

Pero en algún momento te despiertas y te das cuenta de que toda esa maravilla y magia no vienen gratis. A diferencia de sus entusiastas colegas, sus partes interesadas (sí, las personas que le pagan) se preocupan poco por la moda y mucho por el dinero que pagan para construir un producto que pueden vender. Y la conclusión es que es más difícil escribir código inmutable y más fácil de descifrar, además tiene poco sentido tener un front-end inmutable si no tiene un back-end para soportarlo. Cuando (¡y si!) Finalmente convence a sus partes interesadas de que debe publicar y consumir eventos a través de una tecnología push como WebSockets, descubre lo difícil que es escalar la producción .

Ahora para algunos consejos, si decide aceptarlo.

La opción de escribir JavaScript usando FP / Inmutabilidad también es una opción para hacer que la base de código de su aplicación sea más grande, más compleja y más difícil de administrar. Yo argumentaría firmemente por limitar este enfoque a sus reductores Redux ... a menos que sepa lo que está haciendo. En otras palabras: Just Keep It Simple ™. Estarás mejor en la mayoría de los casos. Y donde no esté, me concentraría en obtener los beneficios de los datos inmutables que fluyen a través de su aplicación (completa), en lugar de crear un front-end puramente funcional y hacer que todo funcione.

Ahora, si tiene la suerte de poder tomar decisiones en su trabajo, intente usar su sabiduría (o no) y haga lo correcto por la persona que le paga . Puede basar esto en su experiencia, en su instinto o en lo que sucede a su alrededor (es cierto que si todos usan React / Redux, entonces existe un argumento válido de que será más fácil encontrar un recurso para continuar su trabajo). Alternativamente, puede probar los enfoques de Desarrollo impulsado por reanudación o Desarrollo impulsado por bombo . Podrían ser más tu tipo de cosas.

En resumen, lo que hay que decir sobre la inmutabilidad es que te pondrá de moda con tus compañeros, al menos hasta que llegue la próxima locura, momento en el que estarás contento de seguir adelante.

Ahora he agregado esto como un artículo en mi blog => Inmutabilidad en JavaScript: una vista contraria . Siéntase libre de responder allí si tiene sentimientos fuertes que le gustaría quitarse de su pecho también;).


Creo que la razón principal por la que los objetos inmutables son para mantener válido el estado del objeto.

Supongamos que tenemos un objeto llamado arr . Este objeto es válido cuando todos los artículos son la misma letra.

// this function will change the letter in all the array function fillWithZ(arr) { for (var i = 0; i < arr.length; ++i) { if (i === 4) // rare condition return arr; // some error here arr[i] = "Z"; } return arr; } console.log(fillWithZ(["A","A","A"])) // ok, valid state console.log(fillWithZ(["A","A","A","A","A","A"])) // bad, invalid state

si se arr convierte en un objeto inmutable, nos aseguraremos de que arr esté siempre en un estado válido.


He creado una biblioteca de código abierto agnóstico de marco abierto (MIT) para el estado mutable (o inmutable) que puede reemplazar todos esos almacenamiento inmutable como libs (redux, vuex, etc.).

Los estados inmutables eran feos para mí porque había demasiado trabajo que hacer (muchas acciones para operaciones simples de lectura / escritura), el código era menos legible y el rendimiento para grandes conjuntos de datos no era aceptable (renderizado de componentes completos: /).

Con el observador de estado profundo solo puedo actualizar un nodo con notación de puntos y usar comodines. También puedo crear un historial del estado (deshacer / rehacer / viaje en el tiempo) manteniendo solo esos valores concretos que se han cambiado {path:value} = menos uso de memoria.

Con el observador de estado profundo puedo ajustar las cosas y tengo control de grano sobre el comportamiento de los componentes para que el rendimiento se pueda mejorar drásticamente. El código es más legible y la refactorización es mucho más fácil: solo busque y reemplace las cadenas de ruta (no es necesario cambiar el código / lógica).


Aunque las otras respuestas están bien, para abordar su pregunta sobre un caso de uso práctico (de los comentarios en las otras respuestas) dejemos de lado su código de ejecución por un minuto y miremos la respuesta ubicua justo debajo de su nariz: git . ¿Qué sucedería si cada vez que empujara una confirmación sobrescribiera los datos en el repositorio?

Ahora nos encontramos con uno de los problemas que enfrentan las colecciones inmutables: la hinchazón de memoria. Git es lo suficientemente inteligente como para no simplemente hacer nuevas copias de archivos cada vez que realiza un cambio, simplemente realiza un seguimiento de las diferencias .

Si bien no sé mucho sobre el funcionamiento interno de git, solo puedo suponer que usa una estrategia similar a la de las bibliotecas a las que hace referencia: el intercambio estructural. Bajo el capó, las bibliotecas usan tries u otros árboles para rastrear solo los nodos que son diferentes.

Esta estrategia también es razonablemente eficaz para las estructuras de datos en memoria, ya que existen algoritmos de operación de árbol well-known que operan en tiempo logarítmico.

Otro caso de uso: digamos que desea un botón de deshacer en su aplicación web. Con representaciones inmutables de sus datos, implementarlos es relativamente trivial. Pero si confía en la mutación, eso significa que debe preocuparse por almacenar en caché el estado del mundo y realizar actualizaciones atómicas.

En resumen, hay un precio a pagar por la inmutabilidad en el rendimiento del tiempo de ejecución y la curva de aprendizaje. Pero cualquier programador experimentado le dirá que el tiempo de depuración supera el tiempo de escritura de código en un orden de magnitud. Y el ligero impacto en el rendimiento del tiempo de ejecución probablemente sea superado por los errores relacionados con el estado que sus usuarios no tienen que soportar.


Había una vez un problema con la sincronización de datos entre subprocesos. Este problema fue un gran dolor, había más de 10 soluciones. Algunas personas trataron de resolverlo radicalmente. Era un lugar donde nació la programación funcional. Es como el marxismo. No podía entender cómo Dan Abramov vendió esta idea a JS, porque es de un solo subproceso. El es un genio.

Puedo dar un pequeño ejemplo. Hay un atributo __attribute__((pure)) en gcc. Los compiladores intentan resolver si su función es pura o no, si no la descifrará especialmente. Su función puede ser pura, incluso su estado es mutable. La inmutabilidad es solo una de las más de 100 formas de garantizar que su función sea pura. En realidad, el 95% de sus funciones serán puras.

No debe usar ninguna limitación (como la inmutabilidad) si en realidad no tiene una razón seria. Si desea "Deshacer" algún estado, puede crear transacciones. Si desea simplificar las comunicaciones, puede enviar eventos con datos inmutables. Es tu decision.

Estoy escribiendo este mensaje desde la república posterior al marxismo. Estoy seguro de que la radicalización de cualquier idea es un camino equivocado.


Otro beneficio de la inmutabilidad en Javascript es que reduce el acoplamiento temporal, que tiene beneficios sustanciales para el diseño en general. Considere la interfaz de un objeto con dos métodos:

class Foo { baz() { // .... } bar() { // .... } } const f = new Foo();

Es posible que se requiera una llamada a baz() para que el objeto esté en un estado válido para que una llamada a bar() funcione correctamente. ¿Pero cómo sabes esto?

f.baz(); f.bar(); // this is ok f.bar(); f.baz(); // this blows up

Para resolverlo, debe examinar las partes internas de la clase porque no es inmediatamente evidente al examinar la interfaz pública. Este problema puede explotar en una gran base de código con muchos estados y clases mutables.

Si Foo es inmutable, esto ya no es un problema. Es seguro asumir que podemos llamar a baz o bar en cualquier orden porque el estado interno de la clase no puede cambiar.


Recientemente he estado investigando el mismo tema. Haré todo lo posible para responder sus preguntas y tratar de compartir lo que he aprendido hasta ahora.

La pregunta es, ¿por qué es tan importante la inmutabilidad? ¿Qué tiene de malo mutar objetos? ¿No hace las cosas simples?

Básicamente se reduce al hecho de que la inmutabilidad aumenta la previsibilidad, el rendimiento (indirectamente) y permite el seguimiento de la mutación.

Previsibilidad

La mutación oculta el cambio, que crea efectos secundarios (inesperados), que pueden causar errores desagradables. Cuando aplica la inmutabilidad, puede mantener la arquitectura de su aplicación y el modelo mental simple, lo que facilita razonar sobre su aplicación.

Actuación

Aunque agregar valores a un Objeto inmutable significa que se debe crear una nueva instancia donde se deben copiar los valores existentes y se deben agregar nuevos valores al nuevo Objeto que cuesta memoria, los Objetos inmutables pueden hacer uso del intercambio estructural para reducir la memoria gastos generales.

Todas las actualizaciones devuelven nuevos valores, pero las estructuras internas se comparten para reducir drásticamente el uso de memoria (y la agitación de GC). Esto significa que si agrega un vector con 1000 elementos, en realidad no crea un nuevo vector de 1001 elementos de longitud. Lo más probable es que internamente solo se asignen unos pocos objetos pequeños.

Puedes leer más sobre esto here .

Seguimiento de mutaciones

Además del uso reducido de memoria, la inmutabilidad le permite optimizar su aplicación haciendo uso de la igualdad de referencia y valor. Esto hace que sea realmente fácil ver si algo ha cambiado. Por ejemplo, un cambio de estado en un componente de reacción. Puede usar shouldComponentUpdate para verificar si el estado es idéntico comparando los objetos de estado y evitar la representación innecesaria. Puedes leer más sobre esto here .

Recursos adicionales:

Si configuro decir una matriz de objetos con un valor inicialmente. No puedo manipularlo. Eso es lo que dice el principio de inmutabilidad, ¿verdad? (Corrígeme si me equivoco). Pero, ¿qué sucede si tengo un nuevo objeto de Noticias que debe actualizarse? En el caso habitual, podría haber agregado el objeto a la matriz. ¿Cómo lo logro en este caso? ¿Eliminar la tienda y recrearla? ¿Agregar un objeto a la matriz no es una operación menos costosa?

Si eso es correcto. Si está confundido sobre cómo implementar esto en su aplicación, le recomendaría que vea cómo redux hace esto para familiarizarse con los conceptos básicos, me ayudó mucho.

Me gusta usar Redux como ejemplo porque abarca la inmutabilidad. Tiene un solo árbol de estado inmutable (denominado store ) donde todos los cambios de estado son explícitos mediante el envío de acciones que son procesadas por un reductor que acepta el estado anterior junto con dichas acciones (una a la vez) y devuelve el siguiente estado de su solicitud. Puede leer más sobre sus principios básicos here .

Hay un excelente curso de redux en egghead.io donde Dan Abramov , el autor de redux, explica estos principios de la siguiente manera (modifiqué un poco el código para adaptarlo mejor al escenario):

import React from ''react''; import ReactDOM from ''react-dom''; // Reducer. const news = (state=[], action) => { switch(action.type) { case ''ADD_NEWS_ITEM'': { return [ ...state, action.newsItem ]; } default: { return state; } } }; // Store. const createStore = (reducer) => { let state; let listeners = []; const subscribe = (listener) => { listeners.push(listener); return () => { listeners = listeners.filter(cb => cb !== listener); }; }; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach( cb => cb() ); }; dispatch({}); return { subscribe, getState, dispatch }; }; // Initialize store with reducer. const store = createStore(news); // Component. const News = React.createClass({ onAddNewsItem() { const { newsTitle } = this.refs; store.dispatch({ type: ''ADD_NEWS_ITEM'', newsItem: { title: newsTitle.value } }); }, render() { const { news } = this.props; return ( <div> <input ref="newsTitle" /> <button onClick={ this.onAddNewsItem }>add</button> <ul> { news.map( ({ title }) => <li>{ title }</li>) } </ul> </div> ); } }); // Handler that will execute when the store dispatches. const render = () => { ReactDOM.render( <News news={ store.getState() } />, document.getElementById(''news'') ); }; // Entry point. store.subscribe(render); render();

Además, estos videos demuestran con más detalle cómo lograr la inmutabilidad para: