mozilla

Fonctions fléchées

Cette fonction, proposition pour ECMAScript 6 (Harmony), est expérimentale
Puisque cette fonction est toujours en développement dans certains navigateurs, veuillez consulter le tableau de compatibilité pour les préfixes à utiliser selon les navigateurs.
Il convient de noter qu'une fonctionnalité expérimentale peut voir sa syntaxe ou son comportement modifié dans le futur en fonction des évolutions de la spécification.

Une expression de fonction fléchée (arrow function en anglais) permet d'avoir une syntaxe plus courte que les expressions de fonction et permet de lier la valeur this de façon lexicale. Les fonctions fléchés sont obligatoirement anonymes.

Syntaxe

([param] [, param]) => {
   instructions
}

param => expression

Des exemples plus détaillés, utilisant cette syntaxe, sont disponibles ici (en anglais).

param
Le nom d'un argument. S'il n'y a aucun argument, cela doit être indiqué par une paire de parenthèses (). S'il n'y a qu'un argument, les parenthèses ne sont pas nécessaires. (ex : toto => 1)
instructions ou expression
Plusieurs instructions doivent être encadrées par des accolades, {}. Une expression simple ne nécessite pas d'accolades. L'expression est également la valeur de retour implicite pour cette fonction.

Description

Deux facteurs sont à l'origine de la conception des fonctions fléchées : une syntaxe plus courte et un this lexical.

Voir aussi l'article sur les fonctions fléchées présent sur https://tech.mozfr.org (l'article original en anglais est disponible ici).

Syntaxe plus courte

Pour des aspects fonctionnels, la légèreté de la syntaxe est bienvenue. Par exemple :

var a = [
  "We're up all night 'til the sun",
  "We're up all night to get some",
  "We're up all night for good fun",
  "We're up all night to get lucky"
];

// Sans la syntaxe des fonctions fléchées 
var a2 = a.map(function(s){ return s.length });

// Avec, on a quelque chose de plus concis
var a3 = a.map( s => s.length );

this lexical

Jusqu'avant l'apparition des fonctions fléchées, chaque nouvelle fonction définissait son propre this (un nouvel objet dans le cas d'un constructeur, undefined dans les appels de fonctions stricts, le contexte de l'objet si la fonction est appelée comme une méthode, etc.). Cela a pu entraîner des confusions lorsqu'on utilisait un style de programmation orientée objet.

function Personne() {
  // Le constructeur Personne() définit `this` comme lui-même.
  this.âge = 0;

  setInterval(function grandir() {
    // En mode non strict, la fonction grandir() définit `this` 
    // comme l'objet global et pas comme le `this` defini 
    // par le constructeur Personne().
    this.âge++;
  }, 1000);
}

var p = new Personne();

Avec ECMAScript 3/5, ce problème a pu être résolu en affectant la valeur de this à une autre variable :

function Personne() {
  var self = this; // Certains utilisent `that` plutôt que `self`. Choisissez-en un des deux et soyez cohérents :)
  self.âge = 0;

  setInterval(function grandir() {
    // La fonction callback se réfère à la variable `self` qui est le contexte souhaité
    self.âge++;
  }, 1000);
}

Autrement, on aurait pu utiliser une fonction de liaison afin que la bonne valeur this soit passée à la fonction grandir.

Les fonctions fléchées capturent la valeur this de leur contexte, le code qui suit fonctionne de la façon attendu :

function Personne(){
  this.âge = 0;

  setInterval(() => {
    this.âge++; // |this| réfère bien à l'objet personne
  }, 1000);
}

var p = new Personne();

Liens avec le mode strict

Ici this est lexical, les règles du mode strict sont ignorées pour ce qui concerne this.

var f = () => {'use strict'; return this};
f() === window; // ou l'objet global

Le reste des règles du mode strict sont appliquées normalement.

Appel via Function.prototype.call() ou Function.prototype.apply()

Étant donné que this est déjà lié lexicalement, si on invoque une fonction via la méthode call ou apply, cela ne passera que des arguments mais n'aura aucun effet sur this :

var ajouter = {
  base: 1,

  add : function (a) {
    var f = v => v + this.base;
    return f(a);
  },

  addViaCall: function (a) {
    var f = v => v + this.base;
    var b = {
      base: 2
    };
    return f.call(b, a);
  }
};

console.log(ajouter.add(1));  // Cela affichera 2 dans la console
console.log(ajouter.addViaCall(1)) // Cela affichera toujours 2

Renvoyer des littéraux objets

Attention à bien utiliser les parenthèses lorsqu'on souhaite renvoyer des objets avec des littéraux :

var func = () => { toto: 1 }; // func() renverra undefined !
var func2 = () =>  { toto: function() {} }; // SyntaxError

En effet, ici, l'analyse de l'expression trouve des blocs d'instructions au lieu de littéraux objets. Pour éviter cet effet indésirable, on pourra encadrer le littéral objet :

var func = () => ({ toto: 1 });

Exemples

// Une fonction fléchée vide renvoie undefined
let vide = () => {};

(() => "tototruc")() // renvoie "tototruc" 

var simple = a => a > 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

var complexe = (a, b) => {
  if (a > b) {
    return a;
  } else {
    return b;
  }
}

var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b);  // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2);       // [10, 12, 26, 0, 2, 36, 46]

Spécifications

Spécification Statut Commentaires
ECMAScript 2015 (6th Edition, ECMA-262)
La définition de 'Arrow Function Definitions' dans cette spécification.
Standard Définition initiale.

Compatibilité des navigateurs

Fonctionnalité Chrome Firefox (Gecko) Internet Explorer Opera Safari
Support simple 45.0 22.0 (22.0) Pas de support Pas de support Pas de support
Fonctionnalité Android Webview Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome pour Android
Support simple Pas de support 45.0 22.0 (22.0) Pas de support Pas de support Pas de support 45.0

Notes relatives à Firefox

  • L'implémentation initiale des fonctions fléchées était automatiquement stricte sur Firefox. Cela a été changé avec Firefox 24. Il est désormais nécessaire d'utiliser "use strict";.
  • La sémantique des fonctions fléchées est différente de celle utilisée par les expressions de fermetures ajoutées à Firefox 3 (détails : Javascript 1.8) car pour ces dernières, this n'est pas lié lexicalement.
  • Avant Firefox 39, il était possible d'utiliser une fin de ligne après les arguments d'une fonction fléchée. Cela était incorrect par rapport aux spécifications ES6 et a été réparé. Ainsi, du code tel que () \n => {} déclenchera une exception SyntaxError à partir de cette version (incluse).

Voir aussi

  • L'article sur les fonctions fléchées présent sur https://tech.mozfr.org (l'article original en anglais est disponible ici).

Étiquettes et contributeurs liés au document

Contributeurs à cette page : fscholz, SphinxKnight, BenoitEsnard
Dernière mise à jour par : SphinxKnight,
Masquer la barre latérale