que primer nombre historia guitarrista foo fighters fighter debe coristas album javascript function ecmascript-6

javascript - primer - guitarrista de foo fighters



¿Por qué `obj.foo=function(){};` no asigna el nombre `foo` a la función? (3)

A partir de ES2015 (ES6), las funciones tienen nombres propios (incluida una propiedad de name oficial), y los nombres se asignan cuando la función se crea de varias maneras además de la declaración de función obvia y la expresión de función con nombre, como la asignación a variables (el nombre de la función se establece en el nombre de la variable), asignando a las propiedades del objeto (el nombre de la función se establece en el nombre de la propiedad), incluso los valores predeterminados para los parámetros de la función (el nombre de la función se establece en el nombre del parámetro). Pero asignar a una propiedad en un objeto existente (por ejemplo, no en un inicializador de objeto) no asigna el nombre de esa propiedad a la función. Por qué no? Seguramente debe haber una razón específica por la que no era deseable / posible. ¿Qué era?

Para ser claros: no estoy preguntando cómo solucionarlo. Me pregunto qué impide que este caso aparentemente obvio se maneje cuando hay tantos otros (¡incluidos los valores de parámetros predeterminados!). Debe haber una buena razón.

Por favor, no especules ni teorices. TC39 tenía una razón para no incluirlo. Estoy interesado en cuál fue esa razón. He leído las notas de la reunión TC39 pero aún no la he encontrado. Lo más cercano que he encontrado hasta ahora es que Allen Wirfs-Brock respondió a Bergi para decir que no había consenso para hacerlo de esa forma debido a "varias objeciones", pero lamentablemente no dijo cuáles eran esas objeciones.

Detalles:

Todos los siguientes asignan el nombre foo a la función en un navegador compatible :

// Requires a compliant browser // Assigning to a variable or constant... // ...whether in the initializer... { let foo = function() { }; console.log("1:", foo.name); // "foo" } { const foo = function() { }; console.log("2:", foo.name); // "foo" } // ...or later... { let foo; foo = function() { }; console.log("3:", foo.name); // "foo" } // As an initializer for an object property { const obj = { foo: function() { } }; console.log("4:", obj.foo.name); // "foo" } // Or as a method { const obj = { foo() { } }; console.log("5:", obj.foo.name); // "foo" } // Even if it''s a computed property name { let name = "f"; const obj = { [name + "o" + "o"]() { } }; console.log("6:", obj.foo.name); // "foo" } // As a default value for a parameter (function(foo = function() { }) { console.log("7:", foo.name); // "foo" })(); // ...and a bunch of others

Pero asignar a una propiedad en un objeto existente, fuera de un inicializador de objeto, no:

const obj = {}; obj.foo = function() { }; console.log("Nope:", obj.foo.name);

Por lo que puedo decir, esto está cubierto por esta sección de la especificación, que explícitamente solo establece el nombre de la función si IsIdentifierRef de LeftHandSideExpression es verdadero (que aparentemente no es para referencias de propiedad).

Así que reiterando desde arriba: ¿Por qué no? Seguramente debe haber una razón específica por la que no era deseable / posible. ¿Qué era?


Allen Wirfs-Brock ha respondido en la lista de discusión con las objeciones que impidieron el consenso TC39 sobre la forma obj.foo = function() { } :

...para

cache[getUserSecret(user)] = function() {};

filtraría la información secreta del usuario como el valor del nombre

y para

obj[someSymbol] = function() {}

filtraría el valor del símbolo como el valor del nombre

y para

table[n]=function() {}

nombre probablemente sería una cadena numérica

Hay objeciones a esas objeciones (particularmente la última, que es extremadamente débil; hay muchas otras formas en que a una función se le asigna automáticamente un nombre de cadena numérica), pero ese no es el punto; El punto es que esas fueron las objeciones planteadas.

También agregó que la operación IsPropertyReference que se requeriría (donde actualmente solo hay un IsIdentifierRef) ...

... es una operación de tiempo de ejecución y la nueva semántica requiere la determinación del tiempo de ejecución del valor del nombre. Todo esto es trabajo de tiempo de ejecución adicional que puede ralentizar la creación de cierres de funciones que aparecen dentro de los bucles.

Así que, en general, aparentemente en el momento en que se tomó la decisión, esas objeciones pasaron el día (y posiblemente ahora también), por lo que este formulario no nombra automáticamente las funciones, mientras que muchas otras lo hacen.


Leí las respuestas de Allen Wirfs-Brock, y él habla explícitamente sobre posibles problemas de seguridad. Personalmente estoy de acuerdo con él.

También puede haber problemas de seguridad. La propiedad de nombre se filtra potencialmente a través del objeto de función el nombre de la variable a la que se le asignó inicialmente. Pero no hay mucho que alguien pueda hacer con un nombre de variable local, fuera de la función de origen. Pero un nombre de propiedad filtrado potencialmente conlleva una mayor capacidad.

Parece que las objeciones de las que habla tienen algo que ver con eso. Si TC39 no explicó más su decisión, será difícil descubrir por qué lo dejaron así :).

Lo siento, no puedo ayudarte más.


No estoy seguro de que haya una razón específica.

obj.foo = function (){};

primero crea una referencia para la expresión de función en obj, luego vincula foo a esta referencia que ya tiene un nombre (solo lectura).

Entonces:

obj.fooC = (new Function ()); console.log(obj.fooC.name);//''anonymous'' obj.fooFE = function (){}; console.log(obj.fooFE.name);//'''' obj.fooNFE = function a_name (){}; console.log(obj.fooNFE.name);//''a_name''

Es un comportamiento normal.

¿Hay alguna restricción para escribir:

obj.foo = (function foo(){});