¿Cómo escribo una función de flecha con nombre en ES2015?

Resuelto jhamm asked hace 9 años • 8 respuestas

Tengo una función que estoy intentando convertir a la nueva sintaxis de flecha en ES6 . Es una función con nombre:

function sayHello(name) {
    console.log(name + ' says hello');
}

¿Hay alguna manera de darle un nombre sin una declaración var?

var sayHello = (name) => {
    console.log(name + ' says hello');
}

Obviamente, sólo puedo usar esta función después de haberla definido. Algo como lo siguiente:

sayHello = (name) => {
    console.log(name + ' says hello');
}

¿Existe una nueva forma de hacer esto en ES6 ?

jhamm avatar Jan 16 '15 11:01 jhamm
Aceptado

¿Cómo escribo una función de flecha con nombre en ES2015?

Lo hace de la manera que descartó en su pregunta: lo coloca en el lado derecho de una asignación o inicializador de propiedad donde el motor JavaScript puede usar razonablemente la variable o el nombre de la propiedad como nombre. No hay otra forma de hacerlo, pero hacerlo es correcto y está totalmente cubierto por la especificación. (También funciona para functionexpresiones anónimas tradicionales).

Según la especificación, esta función tiene un nombre verdadero sayHello:

const sayHello = (name) => {
    console.log(name + ' says hello');
};
console.log(sayHello.name); // "sayHello"
Expandir fragmento

Esto se define actualmente en Operadores de asignación > Semántica de tiempo de ejecución: Evaluación , donde realiza la operación abstracta NamedEvalution (actualmente paso 1.ci). (Puede ver en todas partes que esto se aplica al pasar el mouse sobre NamedEvalution en el encabezado y hacer clic en "Referencias".) (Anteriormente, antes de ES2019, Operadores de asignación > Semántica de tiempo de ejecución: Evaluación usaba la operación abstracta SetFunctionName , paso 1.e.iii, pero a partir de ES2019 esta abstracción de especificación fue reemplazada por NamedEvalution).

De manera similar, PropertyDefinitionEvaluación usa NamedEvalution y por lo tanto le da a esta función un nombre verdadero:

let o = {
    sayHello: (name) => {
        console.log(`${name} says hello`);
    }
};

Los motores modernos ya establecen el nombre interno de la función para declaraciones como esa.

Nota : Para que se produzca esta inferencia de nombre, la expresión de la función debe asignarse directamente al objetivo. Por ejemplo, esto no infiere el nombre:

const sayHello = (void 0, (name) => {
    console.log(name + ' says hello');
});
console.log(sayHello.name); // ""
Expandir fragmento

Esto se debe a que la expresión de la función no se asigna directamente al const, es un operando de otro operador (en ese caso, el operador de coma, pero sería lo mismo para [say] true && (name) => { }).

Por ejemplo, en Chrome, Edge (basado en Chromium, v79 en adelante) o Firefox, abra la consola web y luego ejecute este fragmento:

"use strict";
let foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
    foo();
} catch (e) {
    console.log(e.stack);
}
Expandir fragmento

En Chrome 51 y superior y Firefox 53 y superior (y "Legacy" Edge 13 y superior con una marca experimental, o "Chromium" Edge 79 en adelante), cuando lo ejecutes, verás:

foo.nombre es: foo
Error
    en foo (http://stacksnippets.net/js:14:23)
    en http://stacksnippets.net/js:17:3

Tenga en cuenta el foo.name is: fooy Error...at foo.

En Chrome 50 y versiones anteriores, Firefox 52 y versiones anteriores, y Legacy Edge sin la marca experimental, verás esto porque no tienen la Function#namepropiedad (todavía):

foo.nombre es:
Error
    en foo (http://stacksnippets.net/js:14:23)
    en http://stacksnippets.net/js:17:3

Tenga en cuenta que falta el nombre foo.name is:, pero se muestra en el seguimiento de la pila. Es solo que implementar la name propiedad en la función tenía menor prioridad que algunas otras características de ES2015; Chrome y Firefox lo tienen ahora; Edge lo tiene detrás de una bandera, presumiblemente no estará detrás de la bandera por mucho más tiempo.

Obviamente, sólo puedo usar esta función después de haberla definido.

Correcto. No existe una sintaxis de declaración de función para las funciones de flecha, solo una sintaxis de expresión de función , y no hay una flecha equivalente al nombre en una expresión de función con nombre de estilo antiguo ( var f = function foo() { };). Entonces no hay equivalente a:

console.log(function fact(n) {
    if (n < 0) {
        throw new Error("Not defined for negative numbers");
    }
    return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120
Expandir fragmento

Tienes que dividirlo en dos expresiones (yo diría que deberías hacerlo de todos modos) :

const fact = n => {
    if (n < 0) {
        throw new Error("Not defined for negative numbers.");
    }
    return n == 0 ? 1 : n * fact(n - 1);
};
console.log(fact(5));
Expandir fragmento

Por supuesto, si tienes que poner esto donde se requiere una sola expresión, siempre puedes... usar una función de flecha:

console.log((() => {
    const fact = n => {
        if (n < 0) {
            throw new Error("Not defined for negative numbers.");
        }
        return n == 0 ? 1 : n * fact(n - 1);
    };
    return fact(5);
})()); // 120
Expandir fragmento

No digo que sea bonito, pero funciona si absolutamente necesitas un contenedor de expresión único.


Nota al margen: ¿Qué sucede si no desea que una función obtenga su nombre del identificador que está asignando? Eso, ¿y si no quieres example.nameestar "example"aquí?

const example = () => {};
console.log(example.name); // "example"
Expandir fragmento

Puedes evitarlo usando cualquier expresión que no use NamedEvaluación. Probablemente la forma más popular de hacer este tipo de cosas es el operador de coma:

const example = (0, () => {});
//              ^^^−−−−−−−−−^
console.log(example.name); // ""
Expandir fragmento

Puede 0haber cualquier cosa que quieras, se evalúa y luego se desecha, por lo que 0es una opción popular. Pasar la función a través del operador de coma rompe el vínculo directo entre la asignación y la expresión de la función, lo que impide que NamedEvaluación proporcione el nombre examplede la función. (Esto es similar a otros usos famosos del operador de coma, como (0, object.example)()what llama object.example sin ingresar objectel valor de thisdentro de la llamada, o (0, eval)("code"), which hace un eval, pero no en el alcance actual como lo haría normalmente).

(Gracias a Sebastian Simon por plantear este punto en los comentarios).

T.J. Crowder avatar May 27 '2016 16:05 T.J. Crowder

No. La sintaxis de flecha es una abreviatura de funciones anónimas. Las funciones anónimas son, bueno, anónimas.

Las funciones nombradas se definen con la functionpalabra clave.

Jörg W Mittag avatar Jan 16 '2015 05:01 Jörg W Mittag