write w3schools una tipos qué pasar parametros otro llamar lista hace función funciones funcion ejemplos ejemplo desde javascript function-declaration

w3schools - tipos de funciones en javascript



Declaración de función de JavaScript y orden de evaluación (4)

¿Por qué el primero de estos ejemplos no funciona, pero todos los demás sí?

// 1 - does not work (function() { setTimeout(someFunction1, 10); var someFunction1 = function() { alert(''here1''); }; })(); // 2 (function() { setTimeout(someFunction2, 10); function someFunction2() { alert(''here2''); } })(); // 3 (function() { setTimeout(function() { someFunction3(); }, 10); var someFunction3 = function() { alert(''here3''); }; })(); // 4 (function() { setTimeout(function() { someFunction4(); }, 10); function someFunction4() { alert(''here4''); } })();


El alcance de Javascript se basa en funciones, no estrictamente en el alcance léxico. Eso significa que

  • Somefunction1 se define desde el inicio de la función adjunta, pero su contenido no está definido hasta que se le asigna.

  • en el segundo ejemplo, la asignación es parte de la declaración, por lo que se ''mueve'' a la parte superior.

  • en el tercer ejemplo, la variable existe cuando se define el cierre interno anónimo, pero no se usa hasta 10 segundos después, para entonces el valor ha sido asignado.

  • cuarto ejemplo tiene las dos y las terceras razones para trabajar


Esto no es un problema de alcance ni es un problema de cierre. El problema está en la comprensión entre declaraciones y expresiones .

Código JavaScript, ya que incluso la primera versión de JavaScript de Netscape y la primera copia de Microsoft se procesa en dos fases:

Fase 1: compilación: en esta fase, el código se compila en un árbol de sintaxis (y código de bytes o binario según el motor).

Fase 2: ejecución: el código analizado se interpreta.

La sintaxis para la declaración de la función es:

function name (arguments) {code}

Los argumentos son, por supuesto, opcionales (el código también es opcional, pero ¿para qué sirve eso?).

Pero JavaScript también te permite crear funciones usando expresiones . La sintaxis de las expresiones de funciones es similar a las declaraciones de funciones, excepto que están escritas en el contexto de expresión. Y las expresiones son:

  1. Cualquier cosa a la derecha de un signo = (o : en literales de objeto).
  2. Cualquier cosa entre paréntesis () .
  3. Parámetros para funciones (esto ya está cubierto por 2).

Las expresiones a diferencia de las declaraciones se procesan en la fase de ejecución en lugar de en la fase de compilación. Y debido a esto, el orden de las expresiones es importante.

Entonces, para aclarar:

// 1 (function() { setTimeout(someFunction, 10); var someFunction = function() { alert(''here1''); }; })();

Fase 1: compilación. El compilador ve que la variable someFunction se define para que la cree. Por defecto, todas las variables creadas tienen el valor de indefinido. Tenga en cuenta que el compilador no puede asignar valores aún en este punto porque los valores pueden necesitar que el intérprete ejecute algún código para devolver un valor para asignar. Y en este momento todavía no estamos ejecutando el código.

Fase 2: ejecución. El intérprete ve que quieres pasar la variable someFunction a setTimeout. Y así es. Lamentablemente, el valor actual de someFunction no está definido.

// 2 (function() { setTimeout(someFunction, 10); function someFunction() { alert(''here2''); } })();

Fase 1: compilación. El compilador ve que estás declarando una función con el nombre algunaFunción y así la crea.

Fase 2: el intérprete ve que quieres pasar someFunction al setTimeout. Y así es. El valor actual de someFunction es su declaración de función compilada.

// 3 (function() { setTimeout(function() { someFunction(); }, 10); var someFunction = function() { alert(''here3''); }; })();

Fase 1: compilación. El compilador ve que ha declarado una variable someFunction y la crea. Como antes, su valor no está definido.

Fase 2: ejecución. El intérprete pasa una función anónima a setTimeout para que se ejecute más tarde. En esta función, ve que está usando la variable someFunction por lo que crea un cierre a la variable. En este punto, el valor de someFunction aún no está definido. Luego ve que asigna una función a someFunction función. En este punto, el valor de alguna función ya no está indefinido. 1/100 de segundo después, se activan los setTimeout y se llama a algunaFunción. Como su valor ya no está indefinido, funciona.

El caso 4 es realmente otra versión del caso 2 con un poco de caso 3 lanzado. En el punto en que se transfiere alguna función a setTimeout, ya existe debido a que se ha declarado.

Aclaración adicional:

Puede preguntarse por qué setTimeout(someFunction, 10) no crea un cierre entre la copia local de someFunction y la que se pasa a setTimeout. La respuesta a eso es que los argumentos de función en JavaScript siempre, siempre pasan por valor si son números o cadenas o como referencia para todo lo demás. Así que setTimeout en realidad no obtiene la variable que alguna función le pasó (lo que significaría que se está creando un cierre) sino que solo obtiene el objeto al que se refiere alguna función (que en este caso es una función). Este es el mecanismo más utilizado en JavaScript para romper cierres (por ejemplo, en bucles).


Esto suena como un caso básico de seguir un buen procedimiento para evitar problemas. Declare variables y funciones antes de usarlas y declare funciones como esta:

function name (arguments) {code}

Evite declararlos con var. Esto es simplemente descuidado y lleva a problemas. Si adquiere el hábito de declarar todo antes de usarlo, la mayoría de sus problemas desaparecerán a toda prisa. Al declarar variables, las inicializaría con un valor válido de inmediato para asegurar que ninguna de ellas esté indefinida. También tiendo a incluir código que verifica valores válidos de variables globales antes de que una función los use. Esta es una protección adicional contra errores.

Los detalles técnicos de cómo funciona todo esto son algo así como la física de cómo funciona una granada de mano cuando juegas con ella. Mi consejo simple es no jugar con granadas de mano en primer lugar.

Algunas declaraciones simples al principio del código podrían resolver la mayoría de estos tipos de problemas, pero aún podría ser necesaria cierta limpieza del código.

Nota adicional:
Ejecuté algunos experimentos y parece que si declara todas sus funciones de la manera descrita aquí, realmente no importa en qué orden se encuentren. Si la función A usa la función B, la función B no tiene que declararse antes función A.

Entonces, declare primero todas sus funciones, luego sus variables globales, y luego ponga su otro código al final. Sigue estas reglas generales y no puedes equivocarte. Incluso podría ser mejor poner sus declaraciones en el encabezado de la página web y su otro código en el cuerpo para garantizar el cumplimiento de estas reglas.


Porque someFunction1 aún no se ha asignado en el momento en que se setTimeout() la llamada a setTimeout() .

someFunction3 puede parecerse a un caso similar, pero ya que está pasando una función envolviendo someFunction3() a setTimeout() en este caso, la llamada a someFunction3() no se evalúa hasta más adelante.