web-dev-qa-db-fra.com

Pouvez-vous lier des fonctions de flèche?

J'expérimente avec ES6 depuis un moment maintenant et je viens d'arriver à un léger problème.

J'aime beaucoup utiliser les fonctions fléchées, et chaque fois que je le peux, je les utilise.

Cependant, il semblerait que vous ne puissiez pas les lier!

Voici la fonction:

var f = () => console.log(this);

Voici l'objet auquel je souhaite lier la fonction:

var o = {'a': 42};

Et voici comment je lierais f à o:

var fBound = f.bind(o);

Et puis je peux simplement appeler fBound:

fBound();

Ce qui va générer ceci (l'objet o):

{'a': 42}

Cool! Charmant! Sauf que ça ne marche pas. Au lieu de générer l'objet o, il génère l'objet window.

J'aimerais donc savoir: pouvez-vous lier des fonctions de flèche? (Et si oui, comment?)


J'ai testé le code ci-dessus dans Google Chrome 48 et Firefox 43, et le résultat est identique.

81
Florrie

Vous ne pouvez pas "relier" une fonction de flèche. Il sera toujours appelé avec le contexte dans lequel il a été défini. Utilisez simplement une fonction normale.

Extrait du Spécifications ECMAScript 2015 :

Toute référence à des arguments, super, this ou new.target dans une fonction ArrowFunction doit être résolue en une liaison dans un environnement englobant lexicalement. Il s’agit généralement de l’environnement de fonction d’une fonction immédiatement englobante.

90
Nick Tomlin

Pour être complet, vous pouvez associer à nouveau les flèches, vous ne pouvez pas changer le sens de this.

bind a toujours une valeur pour les arguments de la fonction:

((a, b, c) => {
  console.info(a, b, c) // 1, 2, 3
}).bind(undefined, 1, 2, 3)()

Essayez-le ici: http://jsbin.com/motihanopi/edit?js,console

19
cvazac

De la MDN :

Une expression de fonction de flèche a une syntaxe plus courte que celle des expressions de fonction et lie lexicalement la valeur this (ne lie pas ses propres arguments this, arguments, super ou new.target). Les fonctions de flèche sont toujours anonymes.

Cela signifie que vous ne pouvez pas lier une valeur à celle-ci comme vous le souhaitez.

9
Sterling Archer

Pendant des années, les développeurs de js ont eu des difficultés avec la liaison de contexte. Ils ont demandé pourquoi this a changé en javascript, tant de confusion au fil des années en raison de la liaison de contexte et de la différence entre le sens de this en javascript et this dans la plupart des autres OOP langues.

Tout cela m'amène à demander pourquoi, pourquoi! pourquoi voudriez-vous pas relier une fonction de flèche! Celles-ci ont été créées spécialement pour résoudre tous ces problèmes et toutes ces confusions et éviter de devoir utiliser bind ou call ou tout autre moyen permettant de préserver l'étendue de la fonction.

TL; DR

Non, vous ne pouvez pas relier les fonctions de flèche. 

8
taxicala

J'ai posé la même question il y a quelques jours. 

Vous ne pouvez pas lier une valeur car la variable this est déjà liée.

Liaison différente de cette portée à ES6 => opérateur de fonction

3
fos.alex

Les fonctions de flèche ES6 résolvent-elles vraiment «cela» en JavaScript

Le lien ci-dessus explique que les fonctions de flèche this ne changent pas avec les fonctions bind, call, apply.

Il est expliqué avec un très bel exemple.

lancez ceci dans node v4 pour voir le comportement "attendu",

this.test = "attached to the module";
var foo = { test: "attached to an object" };
foo.method = function(name, cb){ 
    // bind the value of "this" on the method 
    // to try and force it to be what you want 
    this[name] = cb.bind(this); };
foo.method("bar", () => { console.log(this.test); });
foo.bar(); 

var obj = {value: 10};
function arrowBind(fn, context) {
  let arrowFn;
  (function() {
    arrowFn = eval(fn.toString());
    arrowFn();
  }).call(context);
}
arrowBind(() => {console.log(this)}, obj);

1
theName

Peut-être que cet exemple vous aidera:

let bob = {
   _name: "Bob",
   _friends: ["stackoverflow"],
   printFriends:(x)=> {
      x._friends.forEach((f)=> {
         console.log(x._name + " knows " + f);
      });
   }
}

bob.printFriends = (bob.printFriends).bind(null,bob);
bob.printFriends();

0
Ehsan