Notre équipe a récemment migré l'ensemble de ses code (de taille moyenne AngularJS app) à partir de CoffeeScript pour JavaScript compilé à l'aide de Traceur. Je suis maintenant à l'aide de la règle suivante pour l'Harmonie des fonctions:
- Utiliser
function
dans la portée globale et pour Object.prototype
propriétés.
- Utiliser
class
pour l'objet des constructeurs.
- Utiliser
=>
partout ailleurs.
Pourquoi utiliser la flèche fonctions presque partout?
- Périmètre de sécurité: Lorsque la flèche de fonctions sont utilisés de manière cohérente, tout est garanti à utiliser le même
thisObject
comme la racine. Si même une seule norme de la fonction de rappel est mélangé avec un tas de flèche fonctions il y a un risque que le champ d'application deviendra foiré.
- Compacité: Flèche de fonctions sont plus faciles à lire et à écrire. (Cela peut paraître opiniâtre alors je vais donner quelques exemples plus loin).
- Clarté: Quand presque tout est une flèche fonction, tout
function
immédiatement bâtons permettant de définir la portée. Un développeur peut toujours regarder vers le haut le côté supérieur function
déclaration de voir ce que l' thisObject
.
Pourquoi toujours utiliser des fonctions sur la portée globale ou de la portée de module?
- Pour indiquer une fonction qui ne doit pas accéder à l'
thisObject
.
- L'
window
objet (de portée mondiale) il est préférable d'aborder de manière explicite.
- Nombre
Object.prototype
définitions de vivre dans la portée globale (pensez - String.prototype.truncate
etc.) et ceux qui ont généralement pour être de type function
de toute façon. L'utilisation systématique function
sur la portée globale permet d'éviter les erreurs.
- De nombreuses fonctions dans la portée mondiale sont l'objet les constructeurs de style ancien définitions de classe.
- Les fonctions peuvent être nommés de1. Ceci a deux avantages: (1) Il est moins difficile à écrire
function foo(){}
que const foo = () => {}
- en particulier en dehors des autres appels de fonction. (2) le nom de La fonction montre dans les traces de pile. Alors qu'il serait fastidieux de nom tous les internes de rappel, le nom de toutes les fonctions publiques est probablement une bonne idée.
Objet constructeurs
D'une tentative d'instancier une flèche fonction lève une exception:
var x = () => {};
new x(); // TypeError: x is not a constructor
Un des principaux avantages de fonctions sur la flèche fonctions est donc que les fonctions de la double objet constructeurs:
function Person(name) {
this.name = name;
}
La fonctionnellement identiques2 ES Harmonie projet de définition de classe est presque aussi compact:
class Person {
constructor(name) {
this.name = name;
}
}
J'attends l'ancienne notation finira par être mal vu. Le constructeur de l'objet de la notation peut être encore utilisée par certains pour simple objet anonyme des usines où les objets sont généré par programmation, mais pas beaucoup d'autre.
Lorsqu'un constructeur de l'objet est nécessaire, on devrait envisager la conversion de la fonction à un class
comme indiqué ci-dessus. La syntaxe fonctionne avec les fonctions anonymes/classes.
La lisibilité de la flèche fonctions
Probablement le meilleur argument pour s'en tenir à des fonctions classiques - champ d'application la sécurité des damnés - serait que la flèche fonctions sont moins lisibles que les fonctions. Si votre code n'est pas fonctionnel en premier lieu, puis flèche fonctions peuvent ne pas sembler nécessaire, et lorsque la flèche fonctions ne sont pas utilisés de manière cohérente, ils moche.
ECMAScript a un peu changé depuis ECMAScript 5.1 nous a donné la fonctionnelle Array.forEach
, Array.map
et l'ensemble de ces fonctionnelles, fonctionnalités de programmation que nous utilisons des fonctions où, pour des boucles aurait été utilisé avant. Asynchronous JavaScript a pris son envol un peu. ES6 sera également expédier un Promise
objet, ce qui signifie encore plus de fonctions anonymes. Il n'y a pas de retour en arrière pour la programmation fonctionnelle. Fonctionnelle JavaScript, flèche fonctions sont préférables plus des fonctions classiques.
Prenez par exemple cette (particulièrement déroutant) morceau de code3:
function CommentCtrl($scope, articles) {
$scope.comments = [];
articles.getList()
.then((articles) => Promise.all(articles.map((article) => article.comments.getList())))
.then((commentLists) => {
$scope.comments = commentLists.reduce((a, b) => a.concat(b));
});
}
Le même bout de code avec des fonctions classiques:
function CommentCtrl($scope, articles) {
$scope.comments = [];
articles.getList()
.then(function (articles) {
return Promise.all(articles.map(function (article) {
return article.comments.getList();
}));
})
.then(function (commentLists) {
$scope.comments = commentLists.reduce(function (a, b) {
return a.concat(b);
});
});
}
Tout en un de la flèche fonctions peut être remplacé par une fonction standard, il y aurait très peu à gagner à le faire. La version est plus lisible? Je dirais que la première.
Je pense que la question de savoir si l'utilisation de la flèche fonctions ou des fonctions classiques deviennent moins pertinentes au fil du temps. La plupart des fonctions sera les méthodes de la classe, qui font de loin avec l' function
mot-clé, ou ils deviennent des classes. Fonctions resteront en usage pour patcher les classes par le biais de l' Object.prototype
. En attendant je vous suggérons de réserver à l' function
mot-clé pour tout ce qui doit vraiment être une méthode d'une classe ou d'une classe.
Notes
- Nommé flèche fonctions ont été reportés dans l'ES6 spec. Ils pourraient encore être ajoutés une future version.
- Selon le projet de norme "déclarations de Classe/les expressions de créer une fonction constructeur/prototype paire exactement comme pour les déclarations de fonction" tant qu'une classe n'utilise pas l'
extend
mot-clé.
- Note sur des blocs dans un état unique flèche fonctions: j'aime utiliser un bloc où une flèche fonction est appelée pour le côté effet seul (par exemple, la cession). De cette façon, il est clair que la valeur de retour peut être mis au rebut.