Comprensión profunda de funciones anónimas en JavaScript

Este artículo se deriva de una pregunta de Zhihu:

Lo mismo es determinar las funciones en tiempo de ejecución, ¿por qué bes función anónima?


Para esta pregunta aparentemente simple, trabajé en el navegador durante más de una hora. Y parece haber descubierto 2 errores sospechosos en FireFox / Chrome Devtools.

En la especificación ES, hay una función interna que se IsAnonymousFunctionDefinition()usa para determinar si una función es una función anónima, pero esta función solo se usa en la especificación y no puede ser llamada por código JS, muchos motores JS lograrán esta función (no obligatoria) internamente.

Cuando hablamos de funciones anónimas, en realidad hay 2 significados diferentes:

  1. La función no tiene nombre

  2. La función de la namepropiedad es"anonymous"

Debido a que la función namese hereda Function.prototype.namey, por lo tanto, la función sin un nameatributo de nombre es el carácter nulo "".

En la mayoría de las herramientas de depuración, las funciones sin nombre se mostrarán como <anonymous>funciones anónimas.

Reescribamos el código en el título:

var a = () => () => { throw new Error('foo') }

O a()()bien var b = a(); b(), ejecutar en Chrome:

Se puede ver claramente que esta función es una función anónima. (Ignore la función anónima inferior, que es Global Scope)

La pila de llamadas en FireFox es:

Esto es tan fascinante. Independientemente de cómo llamar a buna función, ano debería aparecer en la pila de llamadas, creo que esto debería considerarse como un error de FireFox.

Si usa una new Functionfunción personalizada, la pila no es corchetes angulares incorrectos. Porque de acuerdo con la especificación, use la Functionfunción definida que tiene un nombre, el nombre es "anonymous". Es como una persona llamada Anónimo, no porque no tenga nombre, sino porque su apellido es Wuming.

Al lidiar con esto, Firefox es un poco mejor:

var a = new Function('throw new Error("bar")')
a()

Captura de pantalla de FireFox:

Veamos de nuevo Chrome Devtools:

Estoy un poco confundido, tal vez la pila de llamadas dentro del motor se haya descargado. Creo que esto también puede considerarse un error.

El principal problema de preguntarse por qué var a = () => () => 1el nombre de la función ay var b = a()es la función anónima.

La explicación simple es que var a = () => 1contiene 2 etapas, definición de función de flecha y operación de asignación. Todas las funciones son funciones anónimas flecha, flechas en la definición de la función, la especificación interna de hasNameatributos para directamente false. Luego IsAnonymousFunctionDefinition(expr)determine que la función es una función anónima:

  • Si IsFunctionDefinitionde expres decir false, el retorno false.

  • Sea hasNameHasName de expr .

  • Si hasNamees así true, regresefalse .

  • Regreso true.

Al asignar, primero determinará si rvalue es una función anónima. Si es así, restablezca el nombre de la función.

Veamos otra declaración: var b = a(). Esto también incluye operaciones de asignación y una operación de llamada de función.

Solo cuando una función anónima (semántica estática) realiza una operación de asignación, la variable (rval) restablecerá el atributo de nombre, es decir, el nombre de la función. Aquí, un () es solo una llamada de función, no una definición de función, por lo que el nombre de la función no se restablecerá.

parecido:

var a = (1, () => 'foo')
a = [() => 1][0]
var a = eval('()=>1')

Todas son funciones anónimas.

Supongo que te gusta

Origin blog.csdn.net/vCa54Lu0KV27w8ZZBd/article/details/105479429
Recomendado
Clasificación