En JavaScript, una función no es una "estructura mágica del lenguaje", sino un tipo especial de valor.
La sintaxis que usamos antes se llama Declaración de función :
función decir Hola() { alerta( "Hola" ); }
Existe otra sintaxis para crear una función que se llama expresión de función .
Nos permite crear una nueva función en medio de cualquier expresión.
Por ejemplo:
digamosHola = función() { alerta( "Hola" ); };
Aquí podemos ver una variable sayHi
obteniendo un valor, la nueva función, creada como function() { alert("Hello"); }
.
Como la creación de la función ocurre en el contexto de la expresión de asignación (al lado derecho de =
), esta es una Expresión de Función .
Tenga en cuenta que no hay ningún nombre después de la palabra clave function
. Se permite omitir un nombre para las expresiones de función.
Aquí lo asignamos inmediatamente a la variable, por lo que el significado de estos ejemplos de código es el mismo: "crea una función y colócala en la variable sayHi
".
En situaciones más avanzadas, que veremos más adelante, se puede crear una función y llamarla o programarla inmediatamente para una ejecución posterior, sin almacenarla en ningún lugar, por lo que permanece anónima.
Reiteremos: no importa cómo se cree la función, una función es un valor. Ambos ejemplos anteriores almacenan una función en la variable sayHi
.
Incluso podemos imprimir ese valor usando alert
:
función decir Hola() { alerta( "Hola" ); } alerta (di Hola); //muestra el código de la función
Tenga en cuenta que la última línea no ejecuta la función porque no hay paréntesis después de sayHi
. Hay lenguajes de programación donde cualquier mención del nombre de una función provoca su ejecución, pero JavaScript no es así.
En JavaScript, una función es un valor, por lo que podemos tratarla como un valor. El código anterior muestra su representación de cadena, que es el código fuente.
Seguramente, una función es un valor especial, en el sentido de que podemos llamarla como sayHi()
.
Pero sigue siendo un valor. Entonces podemos trabajar con él como con otros tipos de valores.
Podemos copiar una función a otra variable:
función decir Hola() { // (1) crear alerta( "Hola" ); } let func = decir Hola; // (2) copiar función(); // Hola // (3) ejecuta la copia (¡funciona)! decir Hola(); // Hola // esto también funciona (por qué no)
Esto es lo que sucede arriba en detalle:
La Declaración de función (1)
crea la función y la coloca en la variable denominada sayHi
.
La línea (2)
lo copia en la variable func
. Tenga en cuenta nuevamente: no hay paréntesis después de sayHi
. Si lo hubiera, entonces func = sayHi()
escribiría el resultado de la llamada sayHi()
en func
, no la función sayHi
en sí.
Ahora la función se puede llamar tanto como sayHi()
como func()
.
También podríamos haber usado una expresión de función para declarar sayHi
, en la primera línea:
let sayHola = function() { // (1) crear alerta( "Hola" ); }; let func = decir Hola; //...
Todo funcionaría igual.
¿Por qué hay un punto y coma al final?
Quizás se pregunte por qué las expresiones de función tienen un punto y coma ;
al final, pero las declaraciones de funciones no:
función decir Hola() { //... } digamosHola = función() { //... };
La respuesta es simple: aquí se crea una expresión de función como function(…) {…}
dentro de la declaración de asignación: let sayHi = …;
. El punto y coma ;
se recomienda al final de la declaración, no forma parte de la sintaxis de la función.
El punto y coma estaría ahí para una asignación más simple, como let sayHi = 5;
, y también está ahí para una asignación de función.
Veamos más ejemplos de cómo pasar funciones como valores y usar expresiones de funciones.
Escribiremos una función ask(question, yes, no)
con tres parámetros:
question
Texto de la pregunta
yes
Función a ejecutar si la respuesta es “Sí”
no
Función a ejecutar si la respuesta es “No”
La función debe hacer la question
y, dependiendo de la respuesta del usuario, llamar yes()
o no()
:
función preguntar(pregunta, si, no) { si (confirmar (pregunta)) sí() de lo contrario no(); } función mostrarAceptar() { alerta( "Estuviste de acuerdo." ); } función mostrarCancelar() { alert("Cancelaste la ejecución."); } // uso: las funciones showOk, showCancel se pasan como argumentos para preguntar preguntar("¿Estás de acuerdo?", mostrarOk, mostrarCancelar);
En la práctica, estas funciones son bastante útiles. La principal diferencia entre una ask
de la vida real y el ejemplo anterior es que las funciones de la vida real utilizan formas más complejas para interactuar con el usuario que una simple confirm
. En el navegador, estas funciones suelen dibujar una bonita ventana de preguntas. Pero esa es otra historia.
Los argumentos showOk
y showCancel
de ask
se denominan funciones de devolución de llamada o simplemente devoluciones de llamada .
La idea es que pasemos una función y esperemos que la "vuelvan a llamar" más tarde si es necesario. En nuestro caso, showOk
se convierte en la devolución de llamada para la respuesta "sí" y showCancel
para la respuesta "no".
Podemos usar expresiones de funciones para escribir una función equivalente y más corta:
función preguntar(pregunta, si, no) { si (confirmar (pregunta)) sí() de lo contrario no(); } preguntar( "¿Estás de acuerdo?", function() { alert("Estuviste de acuerdo."); }, function() { alert("Cancelaste la ejecución."); } );
Aquí, las funciones se declaran directamente dentro de la llamada ask(...)
. No tienen nombre y por eso se les llama anónimos . No se puede acceder a dichas funciones fuera de ask
(porque no están asignadas a variables), pero eso es justo lo que queremos aquí.
Este código aparece en nuestros scripts de forma muy natural, está en el espíritu de JavaScript.
Una función es un valor que representa una "acción"
Los valores regulares como cadenas o números representan los datos .
Una función puede percibirse como una acción .
Podemos pasarlo entre variables y ejecutarlo cuando queramos.
Formulemos las diferencias clave entre declaraciones y expresiones de funciones.
Primero, la sintaxis: cómo diferenciarlos en el código.
Declaración de función: una función, declarada como una declaración separada, en el flujo de código principal:
// Declaración de función función suma(a, b) { devolver a + b; }
Expresión de función: una función, creada dentro de una expresión o dentro de otra construcción de sintaxis. Aquí, la función se crea en el lado derecho de la "expresión de asignación" =
:
// Expresión de función sea suma = función (a, b) { devolver a + b; };
La diferencia más sutil es cuando el motor JavaScript crea una función.
Una Expresión de Función se crea cuando la ejecución llega a ella y es utilizable solo a partir de ese momento.
Una vez que el flujo de ejecución pasa al lado derecho de la asignación, let sum = function…
– aquí vamos, la función se crea y se puede usar (asignar, llamar, etc.) de ahora en adelante.
Las declaraciones de funciones son diferentes.
Se puede llamar a una declaración de función antes de su definición.
Por ejemplo, una Declaración de función global es visible en todo el script, sin importar dónde se encuentre.
Esto se debe a algoritmos internos. Cuando JavaScript se prepara para ejecutar el script, primero busca declaraciones de funciones globales en él y crea las funciones. Podemos pensar en ello como una "etapa de inicialización".
Y después de procesar todas las declaraciones de funciones, se ejecuta el código. Entonces tiene acceso a estas funciones.
Por ejemplo, esto funciona:
decir Hola("Juan"); // Hola, Juan función decir Hola (nombre) { alerta(`Hola, ${nombre}`); }
La declaración de función sayHi
se crea cuando JavaScript se está preparando para iniciar el script y es visible en todas partes.
…Si fuera una expresión de función, entonces no funcionaría:
decir Hola("Juan"); // ¡error! let sayHola = function(name) { // (*) ya no hay magia alerta(`Hola, ${nombre}`); };
Las expresiones de función se crean cuando la ejecución las alcanza. Eso sucedería sólo en la línea (*)
. Demasiado tarde.
Otra característica especial de las declaraciones de funciones es su alcance de bloque.
En modo estricto, cuando una Declaración de función está dentro de un bloque de código, es visible en todas partes dentro de ese bloque. Pero no fuera de él.
Por ejemplo, imaginemos que necesitamos declarar una función welcome()
dependiendo de la variable age
que obtenemos durante el tiempo de ejecución. Y luego planeamos usarlo algún tiempo después.
Si utilizamos la Declaración de función, no funcionará según lo previsto:
let age = Prompt("¿Cuál es tu edad?", 18); // declarar condicionalmente una función si (edad < 18) { función bienvenida() { alerta("¡Hola!"); } } demás { función bienvenida() { alerta("¡Saludos!"); } } // ...úsalo más tarde bienvenido(); // Error: la bienvenida no está definida
Esto se debe a que una Declaración de Función sólo es visible dentro del bloque de código en el que reside.
Aquí hay otro ejemplo:
sea edad = 16; // toma 16 como ejemplo si (edad < 18) { bienvenido(); // (se ejecuta) // | función bienvenida() { // | alerta("¡Hola!"); // | La declaración de función está disponible } // | en todas partes del bloque donde está declarado // | bienvenido(); // / (corre) } demás { función bienvenida() { alerta("¡Saludos!"); } } // Aquí se nos acabaron las llaves, // por lo que no podemos ver las declaraciones de funciones realizadas dentro de ellos. bienvenido(); // Error: la bienvenida no está definida
¿Qué podemos hacer para que welcome
sea visible fuera de if
?
El enfoque correcto sería utilizar una expresión de función y asignar welcome
a la variable que se declara fuera de if
y tiene la visibilidad adecuada.
Este código funciona según lo previsto:
let age = Prompt("¿Cuál es tu edad?", 18); démosle la bienvenida; si (edad < 18) { bienvenido = función() { alerta("¡Hola!"); }; } demás { bienvenido = función() { alerta("¡Saludos!"); }; } bienvenido(); // bien ahora
¿O podríamos simplificarlo aún más usando un operador de signo de interrogación ?
:
let age = Prompt("¿Cuál es tu edad?", 18); dejar bienvenido = (edad <18)? función() { alerta("¡Hola!"); } : función() { alerta("¡Saludos!"); }; bienvenido(); // bien ahora
¿Cuándo elegir declaración de función versus expresión de función?
Como regla general, cuando necesitamos declarar una función, lo primero que debemos considerar es la sintaxis de la declaración de función. Da más libertad sobre cómo organizar nuestro código, porque podemos llamar a dichas funciones antes de que se declaren.
Eso también es mejor para la legibilidad, ya que es más fácil buscar function f(…) {…}
en el código que let f = function(…) {…};
. Las declaraciones de funciones son más "llamativas".
…Pero si una Declaración de Función no nos conviene por algún motivo, o necesitamos una declaración condicional (acabamos de ver un ejemplo), entonces se debe utilizar la Expresión de Función.
Las funciones son valores. Se pueden asignar, copiar o declarar en cualquier lugar del código.
Si la función se declara como una declaración separada en el flujo de código principal, eso se denomina "Declaración de función".
Si la función se crea como parte de una expresión, se denomina "Expresión de función".
Las declaraciones de funciones se procesan antes de ejecutar el bloque de código. Son visibles en todas partes del bloque.
Las expresiones de función se crean cuando el flujo de ejecución las alcanza.
En la mayoría de los casos, cuando necesitamos declarar una función, es preferible una Declaración de función, porque es visible antes de la declaración misma. Eso nos da más flexibilidad en la organización del código y, por lo general, es más legible.
Por lo tanto, debemos usar una expresión de función solo cuando una declaración de función no sea adecuada para la tarea. Hemos visto un par de ejemplos de eso en este capítulo y veremos más en el futuro.