Estado en JavaScript explicado cocinando una comida sencilla

Si alguna vez ha cocinado una comida en casa, entonces puede comprender cómo escribir código con estado utilizando métodos de programación orientados a objetos en JavaScript.

Cuando comienza a escribir programas simples de JavaScript, no necesita preocuparse por la cantidad de variables que está utilizando o cómo las diferentes funciones y objetos trabajan juntos.

Por ejemplo, la mayoría de las personas comienzan utilizando muchas variables globales o variables que tienen un alcance en el nivel superior del archivo. No forman parte de ninguna clase, objeto o función individual.

Por ejemplo, esta es una variable global llamada estado :

let state = "global";

Pero una vez que su programa comience a involucrar muchas funciones y / u objetos diferentes, necesitará crear un conjunto de reglas más riguroso para su código.

Aquí es donde entra en juego el concepto de Estado. Estado describe el estado de todo el programa o de un objeto individual. Puede ser texto, un número, un booleano u otro tipo de datos.

Es una herramienta común para coordinar código. Por ejemplo, una vez que actualiza el estado, un montón de funciones diferentes pueden reaccionar instantáneamente a ese cambio.

Este artículo describe el estado en el contexto de React, una popular biblioteca de JavaScript.

¿Pero adivina que? ¡Incluso el estado puede darte dolores de cabeza una vez que tu código se complica! Cambiar de estado puede tener consecuencias no deseadas.

Detengámonos ahí mismo. State es una herramienta popular en programación orientada a objetos o POO. Pero muchos programadores prefieren la programación funcional, lo que desalienta los cambios de estado. JavaScript admite ambos paradigmas.

Bien, eso es mucha terminología a la vez. Quería encontrar una manera de mostrar cómo la programación orientada a objetos y la programación funcional pueden lograr los mismos objetivos, incluso si la programación funcional no usa el estado.

Este tutorial mostrará cómo puede cocinar una comida de espaguetis y salsa desde una perspectiva orientada a objetos y funcional.

Aquí hay una vista previa rápida de los dos enfoques diferentes:

Saltemos a eso. Para comprender este tutorial, solo necesita comprender las funciones y los objetos en JavaScript.

Método orientado a objetos (usando estado)

En el gráfico de arriba, mostramos dos enfoques diferentes para hacer esta cena de pasta:

  1. Un método que se centra en el estado de las diferentes herramientas, como el fogón, la olla y la pasta.
  2. Un método que se centra en la progresión de la comida en sí, sin mencionar el estado de las herramientas individuales (ollas, estufas, etc.)

El enfoque orientado a objetos se centra en actualizar el estado, por lo que nuestro código tendrá estado en dos niveles diferentes:

  1. Global, o el estado de toda esta comida.
  2. Local para cada objeto.

Usaremos la sintaxis de ES6 en este tutorial para crear objetos. Aquí hay un ejemplo de estado global y el prototipo "Pot".

let stoveTemp = 500;
function Pot(){ this.boilStatus = ''; this.startBoiling = function(){ if( stoveTemp > 400) this.boilStatus = "boiling"; }}
let pastaPot = new Pot();pastaPot.startBoiling();
console.log(pastaPot);// Pot { boilStatus = 'boiling'; }

Nota: simplifiqué la console.logdeclaración para centrarme en la actualización del estado.

Aquí hay una representación visual de esa lógica:

antes de

Después

Hay dos estados, y cuando pastaPotse crea a través del Potprototipo, inicialmente tiene un vacío boilStatus. Pero luego, hay un cambio de estado.

Ejecutamos pastaPot.startBoiling(), y ahora el boilStatus(estado local) está "hirviendo", ya que el estado global de stoveTempes más de 400.

Ahora vayamos un paso más allá. Dejaremos que la pasta se hierva debido al estado de pastaPot.

Aquí está el código que agregaremos al fragmento de arriba:

function Pasta (){ this.cookedStatus = false; this.addToPot = function (boilStatus){ if(boilStatus == "boiling") this.cookedStatus = true; }}
let myMeal = new Pasta();myMeal.addToPot(pastaPot.boilStatus);
console.log(myMeal.cookedStatus);// true

¡Woah! Eso es mucho a la vez. Esto es lo que sucedió.

  1. Creamos un nuevo prototipo de "Pasta", donde cada objeto tendrá un estado local llamado cookedStatus
  2. Creamos una nueva instancia de Pasta llamada myMeal
  3. Utilizamos el estado del pastaPotobjeto que hemos creado en el último fragmento para determinar si se debe actualizar el estado que se llama cookedStatusen myMealal cocido.
  4. Dado que el estado de boilStatusen pastaPotestaba “hirviendo”, ¡nuestra pasta ahora está cocida!

Aquí está ese proceso visualmente:

antes de

Después

So, we now have the local state of one object, that depends on the local state of another object. And that local state depended on some global state! You can see how this can be challenging. But, it is at least easy to follow for now, since states are updated explicitly.

Functional Method (without state)

In order to fully understand state, you should be able to find a way to accomplish the same outcome as the code above without actually modifying state. This is where functional programming helps!

Functional programming has two core values that separate it from OOP: immutability and pure functions.

I am not going to go into too much depth on those topics, but if you want to learn more, I encourage you to check out this guide to functional programming in JavaScript.

Both of these principles discourage the use of state modification in your code. That means that we can’t use local or global state.

Functional programming instead encourages us to pass in parameters to individual functions. We can use outside variables, but we can’t use them as state.

Here’s an example of a function that will boil the pasta:

const stoveTemp = 500;
const cookPasta = (temp) => { if(temp > 400) return 'cooked';}
console.log(cookPasta(stoveTemp));// 'cooked'

This code will successfully return a string of ‘cooked’. But notice — there is no object that we are updating. The function simply returns the value that will be used in the next step.

Instead, we are focused on the inputs and outputs of one function: cookPasta.

This perspective looks at the transformation of the food itself, rather than the tools that are used to cook it. It’s a little harder to visualize, but we don’t need to have the function depend on external state.

Here’s what it looks like:

Think of it as a “timeline view” for the progress of the meal — this particular function just covers the first part, the transition from dry pasta to cooked pasta.

Now let’s cover the second part as the food is served. Here’s the code that will serve the meal. It will come after the code block above:

const serveMeal = (pasta) => { if (pasta == 'cooked') return 'Dinner is ready.'}
console.log( serveMeal(cookPasta(stoveTemp)) );// 'Dinner is ready.'

Now, we are delivering the results of the cookPasta function directly into the serveMeal function. Again, we are able to do this without changing state, or changing data structures.

Here’s a diagram that uses the “timeline view” to show how these two functions work together:

Interested In More Visual Tutorials?

If you enjoyed this guide, give it a “clap”!

And, if you would like to read more visual tutorials about HTML, CSS and JavaScript, check out the main CodeAnalogies site for 50+ tutorials.