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?
Bon, d'accord, c'est un peu prématuré. Il existe trois petites différences propres aux fonctions fléchées.
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.
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]
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.
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.
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}