web-dev-qa-db-fra.com

Quelles sont les différences (le cas échéant) entre les fonctions fléchées ES6 et les fonctions liées à Function.prototype.bind?

Il me semble que, dans ES6, les deux fonctions suivantes sont très presque identiques:

function () {
  return this;
}.bind(this);

() => {
  return this;
};

Le résultat final semble le même: les fonctions fléchées produisent un objet fonction JavaScript avec leur contexte this lié à la même valeur que le this où elles sont créées.

De toute évidence, au sens général, Function.prototype.bind est plus flexible que les fonctions fléchées: il peut se lier à des valeurs autres que le this local, et il peut lier les this de n'importe quelle fonction à tout moment, potentiellement longtemps après sa création initiale . Cependant, je ne demande pas en quoi bind lui-même est différent des fonctions de flèche, je demande en quoi les fonctions de flèche diffèrent de l'appel immédiat de bind avec this.

Existe-t-il des différences entre les deux constructions dans ES6?

46
Alexis King

Il n'y a pas de différences (significatives).

Bon, d'accord, c'est un peu prématuré. Il existe trois petites différences propres aux fonctions fléchées.

  1. Les fonctions fléchées ne peuvent pas être utilisées avec new.

    Cela signifie, bien sûr, qu'ils n'ont pas de propriété prototype et ne peuvent pas être utilisés pour créer un objet avec la syntaxe d'inspiration classique.

    new (() => {}) // TypeError: () => {} is not a constructor
    

    C'est probablement pour le mieux, cependant - la façon dont new fonctionne n'aurait pas beaucoup de sens avec les fonctions liées.

  2. Les fonctions fléchées n'ont pas accès à l'objet spécial arguments auquel les fonctions JavaScript ordinaires ont accès.

    (() => arguments)(1, 2, 3) // ReferenceError: arguments is not defined
    

    Celui-ci est probablement un peu plus un piège. Vraisemblablement, cela consiste à supprimer l'une des autres bizarreries de JavaScript. L'objet arguments est sa propre bête spéciale , et il a un comportement étrange, il n'est donc pas surprenant qu'il ait été lancé.

    Au lieu de cela, ES6 a des splats qui peuvent accomplir la même chose sans aucune variable cachée magique:

    ((...args) => args)(1, 2, 3) // [1, 2, 3]
    
  3. Les fonctions fléchées n'ont pas leur propre new.target , ils utilisent la propriété new.target de leur fonction englobante, si elle existe.

    Ceci est cohérent avec les autres changements pour supprimer les valeurs introduites "par magie" pour les fonctions fléchées. Ce changement particulier est particulièrement évident, étant donné que les fonctions fléchées ne peuvent pas être utilisées avec new de toute façon, comme mentionné ci-dessus.

Sinon, les flèches sont comme des fonctions liées, sémantiquement. Il est possible que les flèches soient plus performantes, car elles n'ont pas à transporter le bagage supplémentaire et puisqu'elles n'ont pas besoin d'être converties à partir de fonctions ordinaires en premier, mais leur comportement est exactement le même.

34
Alexis King

Il y a quelques différences:

  • Les fonctions fléchées ne peuvent pas être construites. Alors que les fonctions fléchées et les fonctions liées n'ont pas de propriété .prototype, Les premières lèvent une exception lorsqu'elles sont appelées avec new tandis que les secondes ignorent simplement la valeur liée et appellent leur fonction cible comme un constructeur (avec les arguments liés partiellement appliqués, cependant) sur la nouvelle instance.

    function F() {}
    var f = () => {},
        boundF = F.bind({});
    console.log(new boundF(), new boundF instanceof F) // {}, true
    console.log(new f) // TypeError
    
  • Les fonctions fléchées ont également lexical arguments, new.target Et super (pas seulement lexical this). Un appel à une fonction flèche n'initialise aucune de celles-ci, elles sont juste héritées de la fonction dans laquelle la fonction flèche a été définie. Dans une fonction liée, elles se réfèrent simplement aux valeurs respectives de la fonction cible.

  • Les fonctions fléchées ne lient pas réellement une valeur this. Au contraire, ils n'en ont pas, et lorsque vous utilisez this, il ressemble à un nom de variable dans la portée lexicale. Cela vous permet de définir paresseusement une fonction de flèche alors que this n'est pas encore disponible:

    class X extends Object {
        constructor() {
             var f = () => this, // works
                 boundF = function(){ return this; }.bind(this);
    //                                                    ^^^^ ReferenceError
             super(); // initialises `this`
             console.log(f(), f() == this); // {}, true
        }
    }
    new X;
    
  • Les fonctions fléchées ne peuvent pas être des fonctions de générateur (bien qu'elles puissent renvoyer des générateurs). Vous pouvez utiliser .bind() sur une fonction de générateur, mais il n'y a aucun moyen de l'exprimer à l'aide d'une fonction de flèche.

28
Bergi

Voici encore une différence subtile:

Les fonctions fléchées peuvent renvoyer une valeur sans utiliser le mot-clé 'return', en omettant les accolades {} suivant le => immédiatement.

var f=x=>x;           console.log(f(3));  // 3
var g=x=>{x};         console.log(g(3));  // undefined
var h=function(x){x}; console.log(h(3));  // undefined
var i=x=>{a:1};       console.log(i(3));  // undefined
var j=x=>({a:1});     console.log(j(3));  // {a:1}
5
Chong Lip Phang