53 votes

Pourquoi "obj.foo = function() { };`" n'attribue-t-il pas le nom "foo" à la fonction ?

À partir de ES2015 (ES6), les fonctions ont des noms propres (y compris un nom officiel name ), et les noms sont attribués lors de la création de la fonction de diverses manières, en plus de la déclaration de fonction évidente et de l'expression de fonction nommée, comme l'attribution à des variables (le nom de la fonction est défini sur le nom de la variable), l'attribution à des propriétés d'objet (le nom de la fonction est défini sur le nom de la propriété), et même des valeurs par défaut pour les paramètres de fonction (le nom de la fonction est défini sur le nom du paramètre). Mais l'affectation à une propriété d'un objet existant (par exemple, pas dans un initialisateur d'objet) n'affecte pas le nom de cette propriété à la fonction. Pourquoi ? Il doit sûrement y avoir un spécifique raison pour laquelle ce n'était pas souhaitable/possible. Quelle était cette raison ?

Pour être clair : je ne demande pas comment contourner ce problème. Je demande ce qui empêche ce cas apparemment évident d'être traité alors que tant d'autres (y compris les valeurs de paramètres par défaut !) le sont. Il doit y avoir une bonne raison.

S'il vous plaît, ne spéculez pas et ne faites pas de théories. Le TC39 avait une raison de ne pas l'inclure. J'aimerais savoir quelle était cette raison. J'ai parcouru le Notes de réunion du TC39 mais je ne l'ai pas encore trouvé. Le plus proche que j'ai trouvé jusqu'à présent est Allen Wirfs-Brock. en réponse à Bergi pour dire qu'il n'y avait pas de consensus pour le faire pour ce formulaire en raison de "diverses objections", mais malheureusement, il n'a pas dit quelles étaient ces objections.

Détails :

Tous les éléments suivants attribuent le nom foo à la fonction sur un navigateur conforme :

// 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

Mais l'assignation à une propriété sur un objet existant, en dehors d'un initialisateur d'objet, ne le fait pas :

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

Pour autant que je sache, cela est couvert par cet article de la spécification, qui ne définit explicitement le nom de la fonction que si la fonction IsIdentifierRef de la LeftHandSideExpression est vrai (ce qui apparemment ce n'est pas le cas pour les références des propriétés).

Je répète donc ce qui précède : Pourquoi pas ? Il doit sûrement y avoir un spécifique raison pour laquelle ce n'était pas souhaitable/possible. Quelle était cette raison ?

16voto

T.J. Crowder Points 285826

Allen Wirfs-Brock a répondu sur la liste es-discuss avec les objections qui ont empêché le consensus du TC39 sur les obj.foo = function() { } formulaire :

...pour

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

cela divulguerait l'information secrète de l'utilisateur en tant que valeur du nom.

et pour

obj[someSymbol] = function() {}

il y aurait une fuite de la valeur de Symbol comme valeur de name

et pour

 table[n]=function() {}

le nom sera probablement une chaîne numérique

Ces objections peuvent être contrées (en particulier la dernière, qui est extrêmement faible ; il existe de nombreuses autres façons d'attribuer automatiquement à une fonction un nom numérique sous forme de chaîne), mais là n'est pas la question ; la question est que ce sont les objections soulevées.

Il a également ajouté que l'opération IsPropertyReference qui serait nécessaire (alors qu'il n'y a actuellement qu'un IsIdentifierRef)...

...est une opération d'exécution et la nouvelle sémantique exige la détermination de la valeur du nom au moment de l'exécution. Il s'agit d'un travail d'exécution supplémentaire qui peut ralentir la création des fermetures de fonctions qui apparaissent dans les boucles.

Dans l'ensemble, il semble qu'au moment où la décision a été prise, ces objections l'emportaient (et il est fort probable qu'il en serait de même aujourd'hui), ce qui explique pourquoi ce formulaire ne nomme pas automatiquement les fonctions alors que tant d'autres le font.

-2voto

Gabriel Points 215

J'ai lu les réponses d'Allen Wirfs-Brock, et il parle explicitement des problèmes de sécurité possibles. Je suis personnellement d'accord avec lui.

Il peut également y avoir des problèmes de sécurité. La propriété name peut potentiellement laisser échapper, via l'objet fonction, le nom de la variable à laquelle elle est initialement assignée. Mais il n'y a pas grand chose que quelqu'un puisse faire avec le nom d'une variable locale, en dehors de la fonction d'origine. Mais une propriété dont le nom est divulgué est potentiellement porteuse d'une plus grande capacité.

On dirait que les objections dont il parle ont quelque chose à voir avec ça. Si le CT39 n'a pas expliqué davantage sa décision, il est difficile de savoir pourquoi il l'a laissée ainsi :).

Je suis désolé de ne pas pouvoir vous aider davantage.

-2voto

scraaappy Points 2251

Je ne suis pas sûr qu'il y ait une raison spécifique.

obj.foo = function (){};

crée d'abord une référence pour l'expression de la fonction dans obj, puis lie foo à cette référence qui a déjà un nom (en lecture seule).

Donc :

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'

est un comportement normal.

Y a-t-il une restriction pour écrire :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X