De hecho, el término “función anónima”
- es un término común en lenguajes de programación como lo menciona Wikipedia que muestra cómo JavaScript los admite;
- A menudo es utilizado por los depuradores y perfiladores de JS como
- y finalmente está más o menos definido en ECMAScript 2015
La operación abstracta Is AnonymousFunction Definition determina si su argumento es una definición de función que no vincula un nombre.
cf: ES 2015: 14.1.9 Semántica estática: IsAnonymousFunctionDefinition
Como dijo Rick Waldron, es un error común referirse al término “función anónima” siempre que se use una “expresión de función”. Por lo tanto, muchos desarrolladores ni siquiera piensan que sus expresiones de función no tienen que ser expresiones de función “sin nombre”.
Desafortunadamente, la mayoría de los desarrolladores de JS nunca dan nombres a sus expresiones de función, ellos / nosotros perdemos información que puede ser utilizada (y a menudo lo son) por herramientas como editores de código JS (en el esquema), depuradores y perfiladores.
“anónimo” en depuradores Pila de llamadas
Creo que muchos desarrolladores de JS vieron eso
término en la pila de depuradores. Si no, simplemente intente ejecutar este pequeño patrón IIFE en su consola de depuración:
(función () {
depurador
}) ()
o esta matriz para cada llamada ():
[1,2,3] .forEach (function () {
depurador
}) ();
Puede que no sea un gran problema con solo uno de esos o con pequeñas pilas, pero puede volverse bastante molesto cuando el código se vuelve un poco más rico.
Considere dar nombres al menos a su IIFE
(función Inialization_Scope () {
// Código
}) ()
No solo puede salvarlo de una línea de comentarios, sino que dicha información de comentarios también será visible en tiempo de ejecución desde las herramientas de desarrollo del depurador, e incluso a veces en los esquemas del editor de código.
El inspector web recientemente (para un antiguo desarrollador de JS como yo added) agregó un manejo específico cuando se utilizan expresiones de función para crear métodos de objetos. En esta situación, cuando se invoca el método (y luego la “expresión de función anónima”), la pila de llamadas muestra el nombre del método en lugar del nombre de la función:
var obj;
obj = {
métodoA: función () {
depurador // muestra "obj.methodA" en la Pila de llamadas
},
methodB: function namedFunctionExpression () {
depurador // muestra "namedFunctionExpression" en la Pila de llamadas
}
};
obj.methodA ();
obj.methodB ();
El hecho es que, como los métodos son objetos de función que se pueden llamar en muchos contextos diferentes, ambos nombres (nombres de función y método) pueden ser relevantes . Digamos que crea una función (puede ser como una declaración de función). Su nombre representa lo que hace por sí mismo. Lo asigna, de facto por referencia, como un método en diferentes prototipos. Como el contexto de ejecución será diferente, la acción esperada, y el comportamiento real, también pueden ser visualmente diferentes y se podrían dar nombres más apropiados a esos métodos. Mientras trabajo en proyectos con dicho código, ambas informaciones pueden interesarme, ya sea en el contexto de un depurador o incluso un editor de código (a través de esquema, consejos, descripción de autocompletar …).
“anónimo” en la sección de ámbitos del depurador
Cuando se trabaja en proyectos avanzados de JavaScript, la lista de ámbitos de “cierre” entre su alcance “local” y “global” puede ser impresionante en algún momento, y la etiqueta única “cierre” no le ayuda mucho. Te dejo imaginar una vez que obtengas el alcance adicional del bloque ES6
A veces quiero inspeccionar algunas variables desde ámbitos de cierre externos, y todos mis ámbitos suelen tener roles específicos, por lo que los nombro, y esta información a veces es útil para otros desarrolladores / contribuyentes del proyecto. Desafortunadamente (la mayoría) los depuradores todavía no usan esos nombres en la etiqueta de las secciones del alcance del cierre, así que, para encontrar las variables que quiero inspeccionar, hago (lo que creo que mucha gente hace):
- mirar en 2 o 3 secciones de cierre (abrir y cerrar a ciegas algunas de ellas)
- crear expresiones de reloj
Con suerte, a veces sé en qué nivel de cierre están y luego los encuentro rápidamente, pero al hacer los pasos, el nivel podría cambiar y la sección de cierre podría cerrarse automáticamente …
Si usaran los nombres de las funciones, podría encontrar con mayor facilidad las que deseo inspeccionar, y el depurador podría recordar cuál debería permanecer abierto.
ACTUALIZAR:
Creé solicitudes de funciones dedicadas para los principales equipos de herramientas de desarrollo de JS:
- Inspector web de Google Chrome (Problema 493156) (Discusión grupal)
[editar] Ahora está implementado en Chrome y Opera
- Herramientas de desarrollo MS Edge F12
- Herramienta para desarrolladores de Mozilla Firefox
[editar] Ahora está implementado en Firefox
Puedes votar por ellos o comentarlos si te importa
Web Perf: “anónimo” en perfiladores
Es posible que ocasionalmente tenga que buscar problemas de rendimiento. Si la mayoría de sus funciones no tienen nombre, su resumen mostrará cuánto tiempo tarda en ejecutarse la “función anónima” y cuántas veces se ha llamado, pero … esta “función anónima” está en todas partes con muchos tiempos de ejecución diferentes 😉
Tendrá que verificar muchos de ellos para saber realmente qué está sucediendo, y lo peor, una vez que modificó uno de ellos, tendrá dificultades para encontrar dónde está nuevamente para asegurarse de que se solucione el problema.
Por supuesto, generalmente te concentras en funciones que se ejecutan muchas veces y ese “retraso”, pero algunas pueden hacerlo legítimamente, o en algún momento tendrás que arreglar 2, 3 o más de ellas, para poder saber cuál es cuál, y cuál es su propósito realmente ayuda.
nombre de la función en ECMAScript 2015 (también conocido como ES6)
A partir de ECMAScript 2015, las cosas están cambiando y la propiedad del nombre se vuelve oficial. Se define mediante el algoritmo interno SetFunctionName . El hecho de que una función se definió inicialmente con un nombre se verifica mediante el nuevo algoritmo IsAnonymousFunctionDeclaration .
Todavía no es compatible de manera consistente, pero lo que dice es que:
- Si una función se define sin nombre, su propia propiedad de nombre debe establecerse en “predeterminada” (que es un poco diferente a )
console.log ((function () {}). name) // function default ()
// hoy la mayoría de los navegadores devuelven function () o function anonymous ()
- Si tales funciones inicialmente sin nombre se establecen en una variable, esta propiedad de “nombre” propia del objeto de función se actualiza al nombre de la variable
var a = function () {}; console.log(a) // function a()
- Si dichas funciones inicialmente sin nombre se configuran como un método para otro objeto, esta propiedad de “nombre” propia del objeto de función se actualiza a este nombre de propiedad de objeto
a = {b: función () {}}; console.log (ab) // "función b ()"
a = {b () {}}; console.log (ab) // "función b ()"
// algunos depuradores optan por mostrar la función ab () en su lugar
- Si la función se usa para un getter o un setter, se crea una función de cierre y su propia propiedad de nombre se establece en el nombre de la propiedad del objeto con el prefijo “get” o “set”
a = {get b () {depurador; }}; // cierre llamado "get b"
// hoy solo podemos ver "b" en la pila de llamadas en Web Inpector
Es algo bastante bueno, y cubre el caso de uso de las funciones de Arrow.
Entonces, esto soluciona el problema de los métodos y funciones asignados a nombres de variables, pero todavía tenemos un problema con IIFE y las devoluciones de llamada dadas como parámetros de función. Creo que la conveniencia del motor debería ir un poco más allá:
- La devolución de llamada Promise then () y catch () podría heredar fácilmente su nombre del nombre Promise
- la expresión de función anónima directamente dada como parámetros de función (por ejemplo, una matriz para cada devolución de llamada ()), se puede nombrar usando el nombre de la matriz + el nombre del método (por ejemplo: myArrayForEach). Por supuesto, no es perfecto, ya que puede encadenar llamadas map () en una sola matriz con una devolución de llamada diferente (en cuyo caso, la denominación manual es una buena idea), pero aún podría ser mejor que el omnipresente 😉
propiedad de nombre de función
En algunas implementaciones de ECMAScript / JavaScript, el nombre de pila se hace accesible a través de una propiedad propia “nombre” no estándar del objeto de función. Como no puede confiar en él en todas las plataformas, una forma común de obtenerlo es a través del método JavaScript “toString ()”. Para facilitarlo, puede interesarte usar un truco como este:
// Implementa la función # nombre
if (! (función f () {}). nombre) {
Object.defineProperty (Function.prototype, 'name', {
get: function addFunctionNameProperty () {
código var, nombre;
código = Function.prototype.toString.call (esto);
nombre = code.match (/ ^ \ s * function \ s * (\ w *) \ s * \ (/) [1];
Object.defineProperty (esto, 'nombre', {valor: nombre});
nombre de retorno;
}
});
}
basado en el código de una respuesta de Jürg Lehni en Stack Overflow
(solo teniendo cuidado adicional del método toString () específico potencialmente existente en el nivel de instancia).