javascript - validacion - ¿Por qué usar expresiones de función nombradas?
validar formulario javascript html5 (5)
El uso de expresiones de funciones nombradas es mejor cuando se quiere poder hacer referencia a la función en cuestión sin tener que depender de características obsoletas, como arguments.callee
.
Tenemos dos formas diferentes de hacer expresiones de funciones en JavaScript:
Expresión de función nombrada (NFE) :
var boo = function boo () {
alert(1);
};
Expresión de función anónima :
var boo = function () {
alert(1);
};
Y ambos pueden llamarse con boo();
. Realmente no puedo ver por qué / cuándo debería usar funciones anónimas y cuándo debería usar expresiones de funciones con nombre. ¿Qué diferencia hay entre ellos?
En el caso de la expresión de función anónima, la función es anónima , literalmente, no tiene nombre. La variable a la que lo está asignando tiene un nombre, pero la función no. (Actualización: Eso fue cierto a través de ES5. A partir de ES2015 [también conocido como ES6], a menudo una función creada con una expresión anónima obtiene un nombre verdadero, sigue leyendo ...)
Los nombres son útiles. Los nombres se pueden ver en los rastreos de pila, las pilas de llamadas, las listas de puntos de interrupción, etc. Los nombres son una buena cosa ™.
Debe tener cuidado con las expresiones de funciones nombradas en las versiones anteriores de IE (IE8 y siguientes), porque IE crea erróneamente dos objetos de función completamente separados en dos momentos completamente diferentes (más en el artículo doble de mi blog). Si necesita soportar IE8, probablemente sea mejor seguir con las expresiones de funciones anónimas o las declaraciones de funciones, pero evite las expresiones de funciones nombradas.
A partir de ES2015, sin embargo, muchas expresiones de funciones "anónimas" crean funciones con nombres, y esto fue precedido por varios motores modernos de JavaScript que son bastante inteligentes al inferir nombres del contexto. En ES2015, la expresión de función anónima da como resultado una función con el nombre boo
. Esto se encuentra disperso por toda la especificación en lugar de estar definido en un solo lugar con un conjunto de reglas: buscar las apariciones de "SetFunctionName", que se encuentran actualmente en:
- §12.2.6.9 (semántica del inicializador de propiedades)
- §12.14.4 (semántica del operador de asignación)
- §12.14.5.2 y §12.14.5.4 (desestructuración de semánticas de asignación)
- §13.3.1.4 (semántica de declaración
let
yconst
) - ... y un montón de otros lugares.
La versión corta es básicamente cada vez que aparece una expresión de función anónima en el lado derecho de algo así como una asignación o inicialización, como:
var boo = function() { /*...*/ };
(o podría let
o const
lugar de var
) , o
var obj = {
boo: function() { /*...*/ }
};
o
doSomething({
boo: function() { /*...*/ }
});
(los dos últimos son realmente lo mismo) , la función resultante tendrá un nombre ( boo
, en los ejemplos).
Hay una excepción importante e intencional: Asignar a una propiedad en un objeto existente:
obj.boo = function() { /*...*/ }; // <== Does not get a name
Esto se debió a problemas de filtración de información cuando la nueva característica estaba en proceso de ser agregada; detalles en mi respuesta a otra pregunta here .
Las funciones de denominación son útiles si necesitan referenciarse a sí mismas (por ejemplo, para llamadas recursivas). De hecho, si está pasando una expresión de función literal como un argumento directamente a otra función, esa expresión de función no puede referirse directamente a sí misma en el modo estricto ES5 a menos que tenga un nombre.
Por ejemplo, considere este código:
setTimeout(function sayMoo() {
alert(''MOO'');
setTimeout(sayMoo, 1000);
}, 1000);
Sería imposible escribir este código limpiamente si la expresión de la función pasada a setTimeout
fuera anónima; setTimeout
que asignarlo a una variable antes de la llamada a setTimeout
. De esta manera, con una expresión de función nombrada, es un poco más corto y ordenado.
Históricamente, era posible escribir código como este incluso usando una expresión de función anónima, explotando arguments.callee
...
setTimeout(function () {
alert(''MOO'');
setTimeout(arguments.callee, 1000);
}, 1000);
... pero arguments.callee
está en desuso, y está completamente prohibido en el modo estricto ES5. Por lo tanto, MDN aconseja:
Evite usar
arguments.callee()
dando un nombre a las expresiones de función o use una declaración de función donde una función debe llamarse a sí misma.
(énfasis mío)
Si una función se especifica como expresión de función, se le puede asignar un nombre.
Solo estará disponible dentro de la función (excepto IE8-).
Este nombre está destinado a una llamada de función recursiva confiable, incluso si está escrita en otra variable.
Tenga en cuenta que con la declaración de función esto no se puede hacer. Este nombre de función interna "especial" se especifica solo en la sintaxis Expresión de función.
var f = function sayHi(name) {
alert( sayHi ); // Inside the function you can see the function code
};
alert( sayHi ); // (Error: undefined variable ''sayHi'')
Además, el nombre NFE (expresión de función nombrada) no se puede sobrescribir:
var test = function sayHi(name) {
sayHi = "тест"; // try to redefine
alert( sayHi ); // function... (redefinition is unsuccessful )
};
test();
Siempre debe usar expresiones de funciones NOMBRADAS.
- Puede usar el nombre de esa función cuando necesite recurrencia.
2. Funciones Anónimas no ayuda cuando se depura ya que no se puede ver el nombre de la función que causa problemas.
3. Cuando no nombra una función, luego es más difícil entender lo que está haciendo. Darle un nombre lo hace más fácil de entender.
var foo = function bar() {
//some code...
};
foo();
bar(); // Error!
Aquí, por ejemplo, como la barra de nombre se usa dentro de una expresión de función, no se declara en el ámbito externo. Con las expresiones de función nombradas, el nombre de la expresión de la función se incluye dentro de su propio ámbito.