Escuela Frontend
JavaScript

Diferencias Entre Declaraciones de Funciones y Expresiones de Funciones

Horacio Herrera
Autor
Horacio Herrera

En este post veremos las diferencias fundamentales entre declaraciones y expresiones de funciones. ¿Puedes identificarlas? Seguramente has creado funciones de ambas maneras pero, ¿Sabes cuándo usar una o la otra?

Te enseñaré sus diferencias y las maneras en las que puedes usar cada una 👇🏼

Las funciones en cualquier lenguaje de programación son una parte fundamental de cómo organizamos nuestro código. JavaScript al ser un lenguaje dinámico tiene ciertos mecanismos para garantizar que la ejecución de nuestro código sea la más óptima y correcta.

En JavaScript tenemos dos maneras principales de definir funciones, como una declaración o como una expresión.

// declaraciones de función
// Función con nombre
function suma1(a, b) {
return a + b
}
// ========================
// expresiones de función
// Función anónima
var suma2 = function(a, b) {
return a + b
}
// Función con nombre
var suma2 = function suma2(a, b) {
return a + b
}
// Función de flecha (anónima por defecto)
var suma2 = (a, b) => {
return a + b
}

Las diferencias de sintaxis son claras, las expresiones de funciones principalmente están a la DERECHA del símbolo igual, y las declaraciones no lo tienen. ¿Sabes que puedes llamar a una declaración de función antes de la declaración en sí y con las expresiones no?. Veamos por qué esto es posible.

👉🏼 Puedes encontrar el código usado en este artículo en este enlace

Hablemos de Hoisting

Cuando nuestro código JavaScript se ejecuta, el intérprete mueve todas las declaraciones de nuestro programa al inicio. Veamos un ejemplo:

var nombre = "Rick"
var apellido = "Sanchez"
function nombreCompleto(primero, segundo) {
return `${primero} ${segundo}`
}
var pintarEdad = function (numero) {
console.log(`la edad es de ${numero} años`)
}

En el bloque de código anterior podemos ver tanto declaraciones de variables, como asignaciones de valores; y ambas cosas pasan en momentos separados. El intérprete de JavaScript lo que realmente hace es declarar todas las variables y funciones primero antes de asignar y ejecutar cualquier otro valor. Si quisiéramos ver el orden real en el que se va ejecutando cada cosa, sería algo así:

// declaraciones primero
var nombre;
var apellido;
function nombreCompleto(primero, segundo) {
return `${primero} ${segundo}`
}
var pintarEdad;
// asignaciones después
nombre = "Rick"
apellido = "Sanchez"
pintarEdad = function(numero) {
console.log(`la edad es de ${numero} años`)

A este "reorden" se le llama Hoisting. Lo que me gustaría que recuerdes cuando veas la palabra Hoisting en JavaScript, es que tengas claro que la declaración y la inicialización de una variable o función ocurren en momentos distintos, incluso cuando los escribes en la misma línea.

Empecemos con las Diferencias

  • Las declaraciones de funciones pueden ser ejecutadas antes de su definición.
  • Declaraciones a la derecha, expresiones a la izquierda.
  • Las expresiones son más difíciles de inspeccionar.

Las declaraciones de funciones pueden ser ejecutadas antes de su definición

Gracias a que las declaraciones de funciones son ascendidas al momento de ejecución de nuestro programa, nuestra función se puede ejecutar incluso antes de su definición

nuevaFuncion()
function nuevaFuncion() {
console.log("Hola Mundo!")
}
// ➡️ Hola Mundo!

En cambio, esto no es posible con las expresiones de funciones, ya que no se sabe el valor que va a tener nuestra variable previamente declarada.

nuevaFuncion()
var nuevaFuncion = function nuevaFuncion() {
console.log("Hola Mundo!")
}
// ➡️ TypeError: nuevaFuncion is not a function

Declaraciones a la Izquierda, Expresiones a la Derecha

La palabra reservada function se puede usar tanto al lado izquierdo como al lado derecho del signo =. Lo interesante de esto es que siguen diferentes reglas dependiendo de dónde la escribimos.

Cuando la usamos al lado izquierdo, estamos creando una declaración de función y es obligatorio asignar un nombre. En cambio, si la usamos a la derecha del símbolo igual, hablamos de una expresión de función.

// declaración de función
function soyUnaDeclaracion() {
// ...
}
// expresión de función
var soyUnaExpresion = function() {
// ...
}

👉🏼 Dato Curioso: En las expresiones de funciones darle nombre a la función es opcional. En cambio para las declaraciones es obligatorio.

En este último caso, la función pasa a ser una función anónima, algo conveniente ya que nuestro programa sigue funcionando sin problemas, pero puede tener algunas implicaciones a la hora de inspeccionar la cola de ejecución del programa.

Ahora es bastante habitual ver y usar funciones anónimas, ya que las expresiones de función flecha (=>) no permiten asignarles nombre. Utilizar este tipo de declaraciones no es malo, pero tenemos que tener en cuenta las implicaciones que conlleva usarlas. Por un lado, son más legibles y fáciles de usar, pero por otro, son un poco más complejas de inspeccionar y seguir en la cola de ejecución. ¡No te preocupes!, veremos más adelante con más detalle cómo funcionan este tipo de expresiones de función.

Un caso particular en el que una expresión de función no está a la derecha del símbolo igual, es la famosa IIFE (Immediately Invoked Function Expression o Expresión de función ejecutada inmediatamente). Una IIFE es una expresión de función porque la función está encapsulada en paréntesis (()) y crea un "scope" completamente aislado del global. Era una técnica bastante habitual hace unos años (vaya tiempos!)

// la famosa IIFE
(function vayaTiemposCuandoEraFamoso() {
// ...
})()

Las expresiones son más difíciles de inspeccionar

Inevitablemente tendremos problemas en nuestros programas. Poder identificar rápidamente los problemas y saber donde están para resolverlos es fundamental. Cuando le asignamos nombres a nuestras funciones, salen en la cola de ejecución y podemos seguir mejor los errores y ver de donde provienen.

Esto puede ser una opinión no muy popular, pero prefiero utilizar declaraciones de funciones por ser más explícitas y además por las ventajas a la hora de inspeccionar el código. Ésto no quiere decir que no use funciones anónimas o funciones flecha, depende de cada caso, es mejor priorizar la legibilidad o velocidad de análisis e inspección.

Desafío

Mira el siguiente fragmento de código:

init();
const getName = (person) => person.name;
const getAge = (person) => person.age;
const people = [
{
name: "Horacio",
age: "33"
},
{
name: "Matías",
age: "30"
},
{ name: "Lauro", age: "32" }
];
const init = function init(entries) {
const names = entries.map((person) => getName(person));
const ages = entries.map(getAge);
console.log(
`Las personas son ${names.join(", ")} y sus edades son ${ages.join(", ")}`
);
};

Responde a lo siguiente:

  1. ¿Cuántas declaraciones de funciones hay en el programa?
  2. Haz que el programa se ejecute correctamente

Créditos Extra

¿Qué tendrías que hacer para que en el stack trace se puedan identificar bien todas las llamadas a getName?

Considere las siguientes preguntas

Ambas maneras de definir funciones son válidas; ahora que sabemos cómo funcionan cada una:

  • ¿De qué manera nos puede ayudar esta información al momento de organizar nuestro código?
  • ¿Crees que afecta en algo que las expresiones sean de tipo var, let o const? ¿De qué manera puede afectar?
  • ¿En qué casos puede ser útil aprovecharse del Hoisting?

Conclusiones

JavaScript es un lenguaje dinámico y nunca deja de sorprenderme, incluso después de estar usándolo prácticamente cada día, puedo asegurarte que cada día aprendo algo nuevo, así como he aprendido (y re-aprendido) muchas cosas al escribir este artículo. Lo importante que debemos sacar de esto, es la importancia de conocer las implicaciones de usar una u otra. No hay una forma mejor o peor de declarar funciones, lo bueno es conocer las herramientas que tenemos, sus implicaciones y saber cuando podemos usarlas para crear código legible y limpio.

Más recursos

  • La serie de Libros "You don't know JS" de Kyle Simpson me parece que es la biblia sobre JavaScript. Puedes leer los libros gratis en su repositorio
  • Aquí te dejo las notas que recopilé mientras creaba este material
  • Te dejo otra explicación sobre el mismo tema hecha por Tyler: https://ui.dev/arrow-functions/, quizás viendo diferentes puntos de vista te ayuda a entenderlo mejor!

Artículos Relacionados

¿Quieres mejorar tus habilidades de frontend?