Aprende leyendo en orden

Funciones flecha — forma abreviada y cómo devolver objetos

Aprende a reescribir una función con =>, cuándo puedes omitir paréntesis y llaves, cómo devolver un objeto y los cuerpos de bloque.

Incluso para algo corto, como dar formato a cada elemento de un array, una expresión de función te obliga a escribir function, llaves y return cada vez, y la lógica real queda enterrada entre tanta sintaxis.

Este artículo trata las funciones flecha, que crean funciones con =>, y las formas abreviadas que te permiten omitir paréntesis y llaves.

Escribir lo mismo en menos código — la forma básica de la función flecha

Son muy comunes las funciones que reciben un valor, hacen un solo cálculo y devuelven el resultado, como calcular los puntos de recompensa a partir del monto de una compra. Aun así, cada una necesita la palabra function, llaves y return, así que cuando se acumulan expresiones de función, la sintaxis destaca más que los cálculos.

Una función flecha (una forma de crear funciones con =>) se escribe const nombre = (parámetros) => { cuerpo };. Quitas la palabra function y pones => entre la lista de parámetros y el cuerpo; después la asignas a una variable y la llamas igual que una expresión de función.

// Lo que usaste hasta ahora: una expresión de función, que asigna una función a una variable
const rewardPoints = function (price) {
  return price * 0.02;
};

// Función flecha
const rewardPointsArrow = (price) => {
  return price * 0.02;
};

console.log(rewardPoints(3200));        // 64
console.log(rewardPointsArrow(3200));   // 64
console.log(typeof rewardPointsArrow);  // function
De expresión de función a función flecha
Expresión defunciónconst nombre =function (price){ returnprice * 0.02 }Con 3200devuelve 64Funciónflechaconst nombre =(price) =>{ returnprice * 0.02 }Con 3200devuelve 64Solo esto cambia
La asignación y el cuerpo no cambian; solo cambia la parte del medio. Desaparece la palabra function y aparece => después de los parámetros.

Los nombres son distintos solo para poder compararlas lado a lado. En las dos, typeof da function, y las dos reciben los parámetros y usan return exactamente de la misma forma. Si se cumplen ciertas condiciones, puedes acortar todavía más esta forma básica omitiendo los paréntesis o el return.

Reescribe como función flecha yearlyFee, una expresión de función que calcula el precio anual de una suscripción. standardMonthly y premiumMonthly ya están declaradas.

① Convierte yearlyFee en una función flecha sin cambiar su comportamiento.

② Muestra el precio anual de los planes Estándar y Premium como "Estándar: X yenes" y "Premium: X yenes".

③ Muestra la diferencia entre los dos precios de ② como "Diferencia: X yenes".

(Si se ejecuta correctamente, aparecerá una explicación.)

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Omitir paréntesis y return — un solo parámetro y return implícito

Hay lógica que cabe en una sola expresión, como sumarle el envío a un monto o comprobar si un total llega a 5000 yenes. En la forma básica, hasta un cálculo de una línea ocupa tres cuando agregas las llaves y el return, y si se acumulan funciones así, las llaves y el return terminan ocupando casi todo el código.

Si hay exactamente un parámetro, puedes omitir los paréntesis que lo rodean. Y si el cuerpo es una sola expresión, también puedes omitir las llaves y el return. Lo que hace que esto funcione es el return implícito (la regla por la que el valor de la expresión del cuerpo se convierte directamente en el valor de retorno).

// Forma básica: se escriben los paréntesis del parámetro, las llaves del cuerpo y return
const withFee = (price) => {
  return price + 500;
};

// Forma abreviada
const withFeeShort = price => price + 500;
const isFreeShipping = total => total >= 5000;

console.log(withFee(1200));          // 1700
console.log(withFeeShort(1200));     // 1700
console.log(isFreeShipping(4800));   // false
La misma función, cada vez más corta
(price) => {return price + 500; }Sin omitir nadaprice => {return price + 500; }Un parámetro:sin ( )price =>price + 500Una expresión:sin { } ni return
Las tres etapas solo cambian en cómo están escritas; todas hacen el mismo cálculo. Si le pasas 1200 a cualquiera de las tres, obtienes 1700.

El cuerpo de isFreeShipping es una sola comparación, así que si le pasas 4800 devuelve false, el resultado de 4800 >= 5000. El return implícito devuelve el valor al que se evalúa la expresión, así que un cálculo y una comparación se escriben exactamente igual.

Con 0 o 2 parámetros no puedes omitir los paréntesis

Si quitas los paréntesis cuando no hay parámetros, como en () => expresión, o cuando hay dos o más, como en (price, rate) => expresión, obtienes un SyntaxError y el código ni siquiera empieza a ejecutarse. Si más adelante agregas un parámetro, acuérdate de volver a poner los paréntesis. Con un solo parámetro también puedes dejarlos, como en (price) => expresión.

Crea funciones para cotizar un envío, cada una con un cuerpo de una sola expresión. shippingFee y boxCount ya están declaradas.

① Escribe en una línea discountFee, que recibe un costo de envío y devuelve el monto con 10% de descuento (redondeado hacia abajo).

② Escribe en una línea totalFee, que recibe un costo de envío y una cantidad de cajas, y devuelve el envío total.

③ Llama a ① y muestra "Con descuento: X yenes".

④ Pasa el resultado de ① a ② y muestra "Total con descuento: X yenes".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Devolver un objeto — envolverlo entre paréntesis

Cuando preparas un registro para mostrarlo en pantalla, muchas veces lo que quieres devolver no es un solo número, sino un objeto con varias claves. Pero si usas la forma abreviada y escribes las llaves del objeto justo después de =>, obtienes undefined en lugar de un objeto.

Las llaves que escribes después de => se leen como un cuerpo de bloque (una zona donde puedes escribir tantas sentencias como quieras), no como un objeto. Para devolver un objeto, envuélvelo entre paréntesis, como en (name) => ({ name: name }), para que las llaves se lean como una expresión.

// Si escribes las llaves tal cual, se leen como un cuerpo de bloque
const toBadge = (name) => { label: name };
console.log(toBadge("Mouse inalámbrico"));   // undefined

// Entre paréntesis, las llaves se leen como un objeto
const toCard = (name, stock) => ({ name: name, inStock: stock > 0 });
const card = toCard("Mouse inalámbrico", 4);
console.log(JSON.stringify(card));           // {"name":"Mouse inalámbrico","inStock":true}
console.log(card.inStock);                   // true
¿Cuerpo de bloque u objeto?
(name) =>{ label: name }Las llaves se leencomo un bloqueNo hayningún returnDevuelve undefined(name) =>({ label: name })Dentro de ( ):una expresiónLas llaves formanun objetoDevuelveun objeto
Las mismas llaves se leen de forma distinta según estén o no entre paréntesis. Las llaves sin paréntesis se tratan como un cuerpo de bloque sin return.

Con dos o más claves, como en { name: name, inStock: true }, el contenido no se puede interpretar como sentencias, así que un SyntaxError impide que el código se ejecute. Con una sola clave, label: name resulta ser una sentencia válida (una etiqueta seguida de una expresión), así que no hay error y recibes undefined sin ningún aviso, algo fácil de pasar por alto hasta que muestras el resultado.

Arma cotizaciones de envío. orderTotals y freeLine ya están declaradas; el envío cuesta 500 yenes para montos menores que freeLine y es gratis en los demás casos.

① Escribe en una línea toQuote, que recibe un monto y devuelve un objeto con las claves total y shippingFee, en ese orden.

② Muestra la primera cotización con JSON.stringify.

③ De la segunda cotización, muestra "A pagar: X yenes" (monto + envío).

④ Muestra el envío de las dos cotizaciones sumado como "Envío total: X yenes".

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado

Cuando la lógica ocupa varias líneas — cuerpos de bloque y return

Hay lógica que necesita calcular un valor intermedio o separar casos según una condición antes de decidir qué devolver, como calcular cuántos días le quedan a un cliente para devolver un producto. La forma abreviada de una sola expresión no tiene dónde guardar un valor intermedio ni cómo devolver un valor distinto para cada condición.

Un cuerpo de bloque puede contener sentencias como const e if, pero ahí no funciona el return implícito, así que para devolver un valor escribes return. Una función puede tener varios return, y termina en el primero que se ejecute.

// Cuerpo de una sola expresión: el valor de la expresión vuelve tal cual
const shortMessage = (days) => `${days} días desde la compra`;
console.log(shortMessage(12));           // 12 días desde la compra

// Cuerpo de bloque: crea valores intermedios y devuelve un valor según la condición
const returnMessage = (days, isOpened) => {
  const limit = isOpened ? 7 : 14;
  if (days > limit) {
    return "Plazo de devolución vencido";     // Aquí termina la función
  }
  return `Quedan ${limit - days} días`;
};
console.log(returnMessage(12, false));   // Quedan 2 días
console.log(returnMessage(12, true));    // Plazo de devolución vencido

// Sin return, obtienes undefined
const brokenMessage = (days) => { `Quedan ${days} días`; };
console.log(brokenMessage(12));          // undefined
Si el producto se abrió, cambia qué return se ejecuta
returnMessage(12, false)limit es 1412 > 14es falseSigue hasta elúltimo returnreturnMessage(12, true)limit es 712 > 7es trueTermina en elreturn del if
Solo la llamada para un producto abierto llega al return dentro del if. La función termina ahí y nunca llega al return de después.

Si resuelves primero con return los casos que no cumplen la condición, las líneas siguientes solo tienen que ocuparse del caso normal. La tabla de abajo muestra qué recibe quien llama según cómo esté escrito el cuerpo.

CuerpoQué ocurreValor devuelto
days => expresiónDevuelve la expresión12 días desde la compra
(days, isOpened) => { … return }Devuelve el valor de returnQuedan 2 días / Plazo vencido
days => { solo una expresión }Se evalúa, pero no se devuelveundefined

this funciona distinto que en las funciones normales

Dentro del método de un objeto puedes usar this (una palabra clave que se refiere al objeto sobre el que se llamó el método). Una función flecha no tiene su propio this: usa el this del código que la rodea. El artículo sobre clases, en el capítulo de programación orientada a objetos, vuelve sobre esta diferencia.

Calcula cuántas unidades reponer, redondeando a lotes completos. targetStock, currentStock y lotSize ya están declaradas.

① Escribe planRestock como una función flecha con cuerpo de bloque que reciba el stock objetivo, el stock actual y las unidades por lote.

② En el cuerpo, calcula el faltante y devuélvelo redondeado hacia arriba a lotes completos (0 si no falta nada).

③ Llámala con el stock actual y muestra "Reposición: X unidades".

④ Muestra el resultado de la misma forma cuando el stock actual es igual al objetivo.

Editor JavaScript / TypeScript

Ejecutar el código para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1Si declaras const twice = n => n * 2; y muestras twice(4), ¿qué se muestra?

Pregunta 2¿Qué devuelve una llamada a const toItem = name => { label: name };?

Pregunta 3En una función flecha con dos parámetros, ¿qué pasa si omites los paréntesis que los rodean?