6 funciones de JavaScript que debe conocer
Publicado: 2020-09-24Hace poco más de un año hablábamos de las 5 “nuevas” funcionalidades de JavaScript que debes conocer para desarrollarte cómodamente en Gutenberg. Allí aprendimos qué es la desestructuración de objetos y matrices, cómo crear funciones de flecha, qué son los operadores de propagación y reposo, etc. Por suerte, JavaScript todavía tiene muchas funciones que, una vez que esté familiarizado con ellas, lo ayudarán a escribir código más inteligible y breve.
Hoy te mostraré seis funciones de JavaScript realmente geniales. Operadores, ámbito de variables, promesas, funciones asíncronas... ¿estás preparado para aprenderlas todas?
#1 Encadenamiento opcional en JavaScript con el operador ?.
El operador de encadenamiento opcional permite un acceso simplificado a los atributos de un objeto cuando existe la posibilidad de que uno no esté undefined o sea null . Por ejemplo, suponga que tiene un objeto como el siguiente:
const toni = { name: 'Antonio', details: { age: 35, }, }; Para acceder a la age de toni , primero debe acceder al atributo de details y luego a la age :
function getAge( person ) { return person.details.age; } El problema que tenemos en la función anterior, y seguro que no es nada nuevo para ti, es que las propiedades que esperamos que tenga la person no siempre están ahí. Es decir, si person o person.details no están undefined , la función anterior activará un error de tipo:
getAge( toni ); // 35 getAge( {} ); // Uncaught TypeError: person.details is undefinedPor lo general, superamos este problema agregando algunas medidas de seguridad:
function getAge( person ) { if ( ! person ) { return; } if ( ! person.details ) { return; } return person.details.age; } getAge( toni ); // 35 getAge( {} ); // undefined que claramente lo arreglan. Desafortunadamente, la función resultante es más compleja y tiene mucho código ruidoso que desvía nuestra atención de las cosas que realmente importan. Para retomar el camino y arreglar la solución de una manera más simple, todo lo que tenemos que hacer es usar el operador de encadenamiento opcional ?. :
function getAge( person ) { return person?.details?.age; } getAge( toni ); // 35 getAge( {} ); // undefined Esencialmente, este operador nos permite acceder a cada propiedad siempre que no sea undefined o null . Tan pronto como detecta que intentamos acceder a una propiedad de un objeto que no existe, devuelve undefined .
# 2 Operador coalescente nulo ( ?? )
En JavaScript es muy fácil establecer un valor predeterminado para una variable usando este operador: || , ¿Correcto? ¡Incorrecto! Todos hemos hecho esto, pero puede provocar efectos secundarios inesperados si no tiene cuidado...
Por ejemplo, supongamos que tenemos un selector en nuestra tienda Redux que nos permite recuperar un valor establecido por el usuario. Si el usuario aún no ha especificado un valor (es decir, el valor no está undefined ), devolvemos un valor predeterminado usando || :
function getValue( state ) { return state.value || 5; }Ahora, veamos algunos ejemplos de lo que obtendríamos con la función anterior después de que el usuario haya establecido un valor u otro:
// No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 5 ¡Vaya! ¡Todo funcionó bien hasta que llegamos al último caso! Aparentemente, si el usuario establece el valor en 0 , el resultado de la función se convierte en 5 . ¿Por qué? Bueno, la razón es bastante obvia: x||y devuelve y si, y solo si, x es un valor "falso". Esto generalmente funciona bien, ya que undefined es un valor falso. Pero también lo son false o 0 , por ejemplo.
En realidad, solo queríamos establecer un valor default cuando no hay ninguno. Entonces podemos agregar una protección segura para verificar si hay un valor o no:
function getValue( state ) { if ( undefined === state.value ) return 5; return state.value; }e incluso podemos escribirlo usando el operador ternario si nos apetece:
function getValue( state ) { return undefined === state.value ? 5 : state.value; } pero, una vez más, ambas soluciones complican innecesariamente el código. Para asignar un valor predeterminado a una variable, debemos usar el operador coalescente nulo ?? , que devuelve la parte derecha si, y solo si, la parte izquierda es null o undefined :
function getValue( state ) { return state.value ?? 5; }y, ¡sorpresa-sorpresa!, el resultado es exactamente lo que queríamos:
// No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 0Ah, y por cierto, puedes usar este operador combinado con una asignación. Por ejemplo, esto:
value = value ?? 5;es equivalente a esto:
value ??= 5;#3 Promesas y funciones asíncronas
Las promesas son un mecanismo implementado en JavaScript que nos permite simplificar nuestro código fuente cuando trabajamos con operaciones asíncronas, es decir, operaciones cuyos resultados no están disponibles de inmediato. Por ejemplo, si queremos recuperar datos de nuestro servidor, está claro que la respuesta no será instantánea, ya que tenemos que esperar a que el servidor reciba la solicitud, la procese y nos devuelva la respuesta.
En versiones y bibliotecas de JavaScript anteriores (por ejemplo, jQuery), solíamos implementar esto con devoluciones de llamada. La idea era bastante simple: junto con la solicitud en sí, definir la función (la devolución de llamada) que debe llamarse una vez que la respuesta esté disponible. De esta forma, cuando se complete la operación asincrónica (es decir, la recuperación de datos del servidor), la biblioteca llamará a la función y nuestra lógica se reanudará:
jQuery.ajax( { url: 'https://server.com/wp-json/wp/users/1', success: ( user ) => { console.log( user ); }, } );Si solo activamos una única solicitud aislada, esta solución es bastante elegante y conveniente. Pero, tan pronto como necesitamos realizar más solicitudes, las cosas se ensucian rápidamente. Por ejemplo, si queremos solicitar dos usuarios diferentes, tendríamos que anidar las devoluciones de llamada:

jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/1', success: ( user1 ) => { jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/2', success: ( user2 ) => { console.log( user1, user2 ); }, } ); }, } );Las promesas son la solución a este problema: si la obtención de un determinado resultado no es inmediata (como, por ejemplo, cuando recuperamos algo de un servidor), podemos devolver una promesa de JavaScript de inmediato. Este objeto es un envoltorio del valor real y significa la "promesa" de que dicho valor estará disponible en algún momento en el futuro.
Por ejemplo, si tuviéramos que reescribir nuestro primer fragmento usando promesas, se vería así:
const promise = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); promise.then( ( user ) => console.log( user ) ); Como puede ver, wp.apiFetch tiene que recuperar al usuario 1 del servidor, pero da un resultado de inmediato. El resultado, sin embargo, no es el propio usuario, sino una promesa que se resolverá al usuario una vez que se completen las solicitudes. Por lo tanto, todo lo que tenemos que hacer es escribir una devolución de llamada que procesará la respuesta de la promesa cuando se resuelva.
Ahora podrías estar pensando que esto no es tan difícil de lo que teníamos antes, ¿verdad? Después de todo, todavía usamos devoluciones de llamada... pero puede ver lo útil que es esto una vez que empezamos a combinar varias solicitudes:
const promise1 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); const promise2 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/2', } ); Promise.all( [ promise1, promise2 ] ).then( ( [ user1, user2 ] ) => console.log( user1, user2 ); ); Usando promesas, pudimos lanzar dos solicitudes paralelas para recuperar a los usuarios 1 y 2 y usar Promise.all para esperar a que se resolvieran ambas promesas. Sin código de espagueti con devoluciones de llamada anidadas involucradas.
Bueno, lo bueno de las promesas aún está por llegar. Podemos usar algo de azúcar sintáctico para trabajar con promesas de JavaScript y escribir código asíncrono que parezca, bueno, síncrono. Todo lo que tiene que hacer es definir una función asíncrona usando la palabra clave asíncrona y, de repente, las cosas se vuelven mucho más fáciles:
async function logTwoUsers( id1, id2 ) { const user1 = await wp.apiFetch( { url: '…' + id1 } ); const user2 = await wp.apiFetch( { url: '…' + id2 } ); console.log( user1, user2 ); } Cada vez que llame a una operación asíncrona dentro de una función asíncrona, puede esperar su resultado usando la palabra clave await . Lo único que debes tener en cuenta es que, cuando defines una función async , su resultado siempre será una promesa:
async function getNumberFive() { return 5; } const p = getNumberFive(); // a promise p.then( console.log ); // prints "5" #4 Alcance variable cuando se usa let y const
Como probablemente ya sepa, ahora puede declarar variables utilizando las palabras clave let y const . El primero define una variable y el segundo define una constante:
let x = 1; console.log( x ); // 1 x = 2; console.log( x ); // 2 const y = 1; console.log( y ); // 1 y = 2; // Uncaught TypeError: invalid assignment to const 'y' console.log( y ); // 1 Puede sentirse tentado a pensar que let y var son lo mismo, ya que ambas palabras clave nos permiten declarar una variable no constante. Pero hay una diferencia sustancial entre ellos: su alcance. Con let y const , el alcance de la variable es el bloque donde se define. En var , es toda la función.
function fn() { if ( true ) { var x = 1; let y = 2; const z = 3; }//end if console.log( x ); // 1 console.log( y ); // Uncaught ReferenceError: y is not defined console.log( z ); // Uncaught ReferenceError: z is not defined } # 5 Transformación de datos al usar JSON.parse
La función JSON.parse analiza una cadena JSON y crea un objeto JavaScript. Por ejemplo:
const x = JSON.parse( '{"x":1,"a":[1,2,3]}' ); // Object { x: 1, a: [ 1, 2, 3 ] } Lo que la mayoría de la gente no sabe es que admite un segundo argumento llamado reviver . Este parámetro es una función que se ejecutará para cada elemento que se analiza, lo que le permite manipular el valor como desee. Por ejemplo, imagine una cadena JSON como la siguiente:
const json = '{"name":"David","birthday":"1985-12-01T10:00:00.000Z"}'; Si usamos JSON.parse tal como está, generará un objeto con dos atributos de cadena: name y birthday . Pero si proporcionamos una función de JSON.parse reviver podemos asegurarnos de que el birthday se analice como una Date :
const user = JSON.parse( json, ( key, value ) => 'birthday' === key ? new Date( value ) : value ) # 6 Separador numérico en el código fuente usando el carácter Undercore ( _ )
Nuestro último consejo de hoy es el separador numérico. Existe una propuesta (actualmente en la etapa 4) que permite escribir números de una manera que sea más fácil de entender para los humanos. Por ejemplo, ¿realmente puedes decir qué tan grandes son los siguientes números?
10000000000 2189719.25 ¡Si tan solo pudiéramos usar el separador de miles, sería mucho más fácil de interpretar! Y eso es precisamente lo que podemos hacer usando el guión bajo _ :
10_000_000_000 2_189_719.25Resumen
Es posible escribir mejor código JavaScript si te acostumbras a todas las nuevas herramientas y características incluidas en JavaScript. Hoy hemos visto varios ejemplos de lo que es posible con este lenguaje de programación. Espero que hayas aprendido algo nuevo y si te ha gustado no olvides compartirlo con tus compañeros. ¡Nos vemos pronto!
Imagen destacada de Sam Dan Truong en Unsplash.
