Manejo de nulos e indefinidos en JavaScript

Un aspecto del desarrollo de JavaScript con el que luchan muchos desarrolladores es el manejo de valores opcionales. ¿Cuáles son las mejores estrategias para minimizar los errores causados por valores que podrían ser null, undefined o no inicializados en tiempo de ejecución?

Algunos lenguajes tienen prestaciones integradas para esas circunstancias. En algunos lenguajes de tipado estático, puede decir que null y undefined son valores ilegales y dejar que su lenguaje de programación arroje un TypeError en tiempo de compilación , pero incluso en esos lenguajes, eso «no puede evitar que las entradas nulas fluyan al programa en tiempo de ejecución.

Para manejar mejor este problema, necesitamos entender de dónde pueden venir estos valores. Aquí son algunas de las fuentes más comunes:

  • Entrada del usuario
  • Registros de la base de datos / red
  • Estado no inicializado
  • Funciones que podrían no devuelve nada

Cuando se trata de la entrada del usuario, la validación es la primera y mejor línea de defensa. A menudo confío en los validadores de esquemas para ayudar con ese trabajo. Por ejemplo, consulte reaccionar -jsonschema-form.

Registros de hidratación desde la entrada

Siempre paso las entradas que recibo de la red, la base de datos o la entrada del usuario a través de una función de hidratación. Por ejemplo, usaré creadores de acciones redux que pueden manejar

valores para hidratar los registros del usuario:

const setUser = ({ name = "Anonymous", avatar = "anon.png" } = {}) => ({
type: setUser.type,
payload: {
name,
avatar
}
});
setUser.type = "userReducer/setUser";

A veces, necesitará mostrar diferentes cosas según el estado actual de los datos. Si es posible mostrar una página antes de que se inicialicen todos los datos, es posible que se encuentre en esa situación. Por ejemplo, cuando muestra saldos monetarios a un usuario, podría mostrar accidentalmente un saldo de $ 0 antes de que se carguen los datos. He visto esto molestar a los usuarios varias veces. Puede crear tipos de datos personalizados que generen diferentes resultados en función del estado actual:

El código anterior es una máquina de estado que hace que sea imposible mostrar estados no válidos. Cuando cree el saldo por primera vez, se establecerá en un estado uninitialized. Si intenta mostrar un saldo mientras el estado es uninitialized, siempre obtendrá un valor de marcador de posición («--«) en su lugar.

Para cambiar eso, debe establecer explícitamente un valor llamando al método .set o al método abreviado setBalance definimos debajo de la createBalance fábrica.

El estado en sí está encapsulado para protegerlo de interferencias externas para asegurarse de que otras funciones no puedan tomarlo y configurarlo a un estado no válido.

Nota: Si se pregunta por qué usamos cadenas en lugar de números para esto, es porque represento tipos de dinero con cadenas de números grandes con mucha precisión decimal para evitar errores de redondeo y representar con precisión los valores de las transacciones de criptomonedas, que pueden tener una precisión decimal significativa arbitraria.

Si ‘ Si utiliza la arquitectura Redux o Redux, puede declarar máquinas de estado con Redu x-DSM.

Evite crear valores nulos e indefinidos

En sus propias funciones, puede evitar crear null o undefined valores para empezar. Hay un par de formas de hacerlo integradas en JavaScript que me vienen a la mente. Vea a continuación.

Evite nulos

Nunca creo explícitamente null valores en JavaScript, porque nunca vi el sentido de tener dos valores primitivos que esencialmente significan «este valor no existe».

Desde 2015, JavaScript ha admitido valores predeterminados que se completan cuando no se proporciona un valor para el argumento o propiedad en cuestión. Esos valores predeterminados no funcionan para los valores null. Eso suele ser un error, en mi experiencia. Para evitar esa trampa, no use null en JavaScript.

Si desea casos especiales para valores vacíos o sin inicializar, las máquinas de estado son una mejor opción. Consulte más arriba.

Nuevas funciones de JavaScript

Hay un par de funciones que pueden ayudarlo a lidiar con null o undefined valores. Ambas son propuestas de etapa 3 en el momento de escribir este artículo, pero si está leyendo en el futuro, es posible que pueda utilizarlas.

Al momento de escribir este artículo, el encadenamiento opcional es una propuesta de etapa 3. Funciona así:

const foo = {};
// console.log(foo.bar.baz); // throws error
console.log(foo.bar?.baz) // undefined

Operador coalescente nulo

También una propuesta de etapa 3 que se agregará a la especificación, «operador coalescente nulo ”Es básicamente una forma elegante de decir» operador de valor de respaldo «. Si el valor de la izquierda es undefined o null, se evalúa como el valor de la derecha.Funciona así:

Asíncrono O bien con promesas

Si una función puede no regresar con un valor, podría ser una buena idea envolverla en Either. En programación funcional, la mónada Either es un tipo de datos abstracto especial que le permite adjuntar dos rutas de código diferentes: una ruta exitosa o una ruta fallida. JavaScript tiene un tipo de datos monad-ish asincrónico incorporado llamado Promise. Puede usarlo para hacer bifurcaciones de errores declarativos para valores no definidos:

Podría escribir una versión sincrónica de eso si lo desea, pero no la he necesitado mucho. Dejaré eso como un ejercicio para ti. Si tiene una buena base en functores y mónadas, el proceso será más fácil. Si eso suena intimidante, no se preocupe. Solo usa promesas. Están integrados y funcionan bien la mayor parte del tiempo.

Arrays for Maybes

Los arrays implementan un método map que requiere una función que se aplica a cada elemento de la matriz. Si la matriz está vacía, nunca se llamará a la función. En otras palabras, las matrices en JavaScript pueden desempeñar el papel de Maybes en lenguajes como Haskell.

¿Qué es Quizás?

Quizás es un tipo de datos abstracto especial que encapsula un valor opcional . El tipo de datos tiene dos formas:

  • Solo: A Quizás que contiene un valor
  • Nada: a Quizás sin valor

Aquí está la esencia de la idea:

Este es solo un ejemplo para demostrar el concepto. Podría crear una biblioteca completa de funciones útiles en torno a maybes, implementando otras operaciones como flatMap y flat (p. Ej., Para evitar Just(Just(value)) cuando se componen múltiples funciones de retorno de Maybe). Pero JavaScript ya tiene un tipo de datos que implementa muchas de esas características listas para usar, por lo que generalmente busco eso: The Array.

Si desea crear una función que pueda o puede que no produzca un resultado (especialmente si puede haber más de un resultado), es posible que tenga un gran caso de uso para devolver una matriz.

Encuentro el hecho de que map no se llamará en una lista vacía muy útil para evitar los valores null y undefined, pero recuerde, si la matriz contiene valores null y undefined, llamará a la función con esos valores, por lo que si la función que estás ejecutando podría producir null o undefined, tendrás que filtrarlos de tu matriz devuelta, como se demostró anteriormente. Eso podría tener el efecto de cambiar la longitud de la colección.

En Haskell, hay una función maybe que (como ) aplica una función a un valor. Pero el valor es opcional y está encapsulado en un Maybe. Podemos usar el tipo de datos JavaScript «s Array para hacer esencialmente lo mismo:

maybe toma un valor de respaldo , luego una función para mapear sobre la matriz tal vez, luego una matriz tal vez (una matriz que contiene un valor, o nada), y devuelve el resultado de aplicar la función al contenido de la matriz, o el valor de reserva si la matriz es vacío.

Para mayor comodidad, también definí una función toMaybeArray y curvé la función maybe para hacer es más obvio para esta demostración.

Si desea hacer algo como esto en el código de producción, he creado una biblioteca de código abierto probada por unidad para hacerlo más fácil. Se llama Maybearray. La ventaja de Maybearray sobre otras bibliotecas de Maybe de JavaScript es que utiliza matrices de JavaScript nativas para representar valores, por lo que no tiene que darles ningún tratamiento especial ni hacer nada especial para convertir de un lado a otro. Cuando encuentre matrices de Maybe en su depuración, no tiene que preguntar, «¿Qué es este tipo extraño? Es solo una matriz de un valor o una matriz vacía y los ha visto un millón de veces antes.

Pasos siguientes

Hay mucho más contenido en EricElliottJS.com, incluidos muchos de videos, ejercicios, screencasts grabados y sugerencias rápidas. Si no eres miembro, ¡ahora es un buen momento para ver lo que te has estado perdiendo!

Comience su lección gratuita en EricElliottJS.com

Write a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *