L'auteur du matériel, dont nous publions la traduction aujourd'hui, dit qu'après une longue période de programmation orientée objet, il a réfléchi à la complexité des systèmes. Selon
John Ousterhout , la complexité est tout ce qui rend la compréhension ou la modification des logiciels plus difficile. L'auteur de cet article, après avoir effectué quelques recherches, a découvert les concepts de programmation fonctionnelle comme l'immunité et les fonctions pures. L'utilisation de tels concepts vous permet de créer des fonctions qui n'ont pas d'effets secondaires. L'utilisation de ces fonctions simplifie la prise en charge du système et offre au programmeur d'autres
avantages .

Nous parlons ici de programmation fonctionnelle et de certains de ses principes importants. Tout cela sera illustré par de nombreux exemples de code JavaScript.
Qu'est-ce que la programmation fonctionnelle?
Vous pouvez en savoir plus sur la programmation fonctionnelle sur
Wikipedia . À savoir, nous parlons du fait que la programmation fonctionnelle est un paradigme de programmation dans lequel le processus de calcul est traité comme calculant les valeurs des fonctions dans la compréhension mathématique de ces dernières. La programmation fonctionnelle implique de faire le calcul des résultats des fonctions à partir des données source et des résultats d'autres fonctions, et n'implique pas le stockage explicite de l'état du programme. Par conséquent, cela n'implique pas la variabilité de cet état.
Maintenant, à titre d'exemples, nous allons analyser quelques idées de programmation fonctionnelle.
Fonctions pures
Les fonctions pures sont le premier concept fondamental à étudier pour comprendre l'essence de la programmation fonctionnelle.
Qu'est-ce qu'une «fonction pure»? Qu'est-ce qui rend une fonction «propre»? Une fonction pure doit répondre aux exigences suivantes:
- Il renvoie toujours, en lui passant les mêmes arguments, le même résultat (de telles fonctions sont aussi appelées déterministes).
- Une telle fonction n'a pas d'effets secondaires.
Considérez la première propriété des fonctions pures, à savoir le fait qu'elles, en leur passant les mêmes arguments, retournent toujours le même résultat.
▍ Arguments de fonction et valeurs de retour
Imaginez que nous devons créer une fonction qui calcule l'aire d'un cercle. Une fonction qui n'est pas pure prendrait comme paramètre le rayon du cercle (
radius
), après quoi elle renverrait la valeur du calcul de l'expression
radius * radius * PI
:
const PI = 3.14; function calculateArea(radius) { return radius * radius * PI; } calculateArea(10);
Pourquoi cette fonction ne peut-elle pas être appelée pure? Le fait est qu'il utilise une constante globale, qui ne lui est pas transmise comme argument.
Imaginez maintenant que certains mathématiciens sont arrivés à la conclusion que la valeur de la constante
PI
devrait être le nombre
42
, à cause de quoi la valeur de cette constante a été modifiée.
Maintenant, une fonction qui n'est pas pure, lorsqu'elle reçoit la même valeur d'entrée, le nombre
10
, renverra la valeur
10 * 10 * 42 = 4200
. Il s'avère qu'en utilisant ici la même chose que dans l'exemple précédent, la valeur du paramètre
radius
, la fonction renvoie un résultat différent. Corrigeons ceci:
const PI = 3.14; function calculateArea(radius, pi) { return radius * radius * pi; } calculateArea(10, PI);
Maintenant, lors de l'appel de cette fonction, nous lui passerons toujours l'argument
pi
. Par conséquent, la fonction ne fonctionnera qu'avec ce qui lui est transmis lors de son appel, sans recourir à des entités globales. Si nous analysons le comportement de cette fonction, nous pouvons arriver aux conclusions suivantes:
- Si les fonctions passent l'argument de
radius
égal à 10
et l'argument pi
égal à 3.14
, il retournera toujours le même résultat - 314
. - Lorsqu'il est appelé avec un argument de
radius
de 10
et pi
de 42
, il retournera toujours 4200
.
Lecture de fichiers
Si notre fonction lit des fichiers, elle ne sera pas propre. Le fait est que le contenu des fichiers peut changer.
function charactersCounter(text) { return `Character count: ${text.length}`; } function analyzeFile(filename) { let fileContent = open(filename); return charactersCounter(fileContent); }
Génération de nombres aléatoires
Toute fonction qui repose sur un générateur de nombres aléatoires ne peut pas être pure.
function yearEndEvaluation() { if (Math.random() > 0.5) { return "You get a raise!"; } else { return "Better luck next year!"; } }
Parlons maintenant des effets secondaires.
▍ Effets secondaires
Un exemple d'un effet secondaire qui peut se produire lorsqu'une fonction est appelée est la modification de variables globales ou d'arguments passés aux fonctions par référence.
Supposons que nous devions créer une fonction qui prend un entier et incrémente ce nombre par 1. Voici à quoi pourrait ressembler une implémentation d'une idée similaire:
let counter = 1; function increaseCounter(value) { counter = value + 1; } increaseCounter(counter); console.log(counter);
Il existe un
counter
variables globales. Notre fonction, qui n'est pas pure, reçoit cette valeur en argument et la remplace, en ajoutant une à sa valeur précédente.
La variable globale change, similaire dans la programmation fonctionnelle n'est pas la bienvenue.
Dans notre cas, la valeur de la variable globale est modifiée. Comment nettoyer la fonction d'
increaseCounter()
dans ces conditions? En fait, c'est très simple:
let counter = 1; function increaseCounter(value) { return value + 1; } increaseCounter(counter);
Comme vous pouvez le voir, la fonction renvoie
2
, mais la valeur du
counter
variable globale ne change pas. Ici, nous pouvons conclure que la fonction renvoie la valeur qui lui est passée, augmentée de
1
, sans rien changer.
Si vous suivez les deux règles ci-dessus pour écrire des fonctions pures, cela facilitera la navigation dans les programmes créés à l'aide de ces fonctions. Il s'avère que chaque fonction sera isolée et n'affectera pas les parties du programme qui lui sont extérieures.
Les fonctions pures sont stables, cohérentes et prévisibles. En recevant les mêmes données d'entrée, ces fonctions renvoient toujours le même résultat. Cela évite au programmeur d'essayer de prendre en compte la possibilité de situations dans lesquelles le transfert de fonctions des mêmes paramètres conduit à des résultats différents, car cela est tout simplement impossible avec des fonctions pures.
▍ Forces des fonctions pures
Parmi les points forts des fonctions pures, il y a le fait que le code écrit en les utilisant est plus facile à tester. En particulier, vous n'avez pas besoin de créer d'objets de stub. Cela permet des tests unitaires de fonctions pures dans divers contextes:
- Si le paramètre A est transmis à la fonction, la valeur de retour de B est attendue.
- Si le paramètre C est transmis à la fonction, la valeur de retour de D est attendue.
Comme exemple simple de cette idée, nous pouvons donner une fonction qui prend un tableau de nombres, et on s'attend à ce qu'elle augmente d'un chaque numéro de ce tableau, renvoyant un nouveau tableau avec les résultats:
let list = [1, 2, 3, 4, 5]; function incrementNumbers(list) { return list.map(number => number + 1); }
Ici, nous passons un tableau de nombres à la fonction, après quoi nous utilisons la méthode tableau
map()
, qui nous permet de modifier chaque élément du tableau et forme un nouveau tableau renvoyé par la fonction. Nous appelons la fonction en lui passant un tableau de
list
:
incrementNumbers(list);
De cette fonction, il est prévu que, après avoir accepté un tableau de la forme
[1, 2, 3, 4, 5]
, il retournera un nouveau tableau
[2, 3, 4, 5, 6]
. Voilà comment ça fonctionne.
Immunité
L'immunité d'une certaine entité peut être décrite comme le fait qu'elle ne change pas dans le temps, ou comme l'impossibilité de changer cette entité.
S'ils essaient de changer un objet immuable, cela ne réussira pas. Au lieu de cela, vous devrez créer un nouvel objet contenant les nouvelles valeurs.
Par exemple, JavaScript utilise souvent la boucle
for
. Au cours de son travail, comme indiqué ci-dessous, des variables mutables sont utilisées:
var values = [1, 2, 3, 4, 5]; var sumOfValues = 0; for (var i = 0; i < values.length; i++) { sumOfValues += values[i]; } sumOfValues
À chaque itération de la boucle, la valeur de la variable
i
et la valeur de la variable globale (on peut considérer l'état du programme)
sumOfValues
. Comment dans une telle situation maintenir l'immuabilité des entités? La réponse réside dans l'utilisation de la récursivité.
let list = [1, 2, 3, 4, 5]; let accumulator = 0; function sum(list, accumulator) { if (list.length == 0) { return accumulator; } return sum(list.slice(1), accumulator + list[0]); } sum(list, accumulator);
Il existe une fonction
sum()
, qui prend un tableau de nombres. Cette fonction s'appelle jusqu'à ce que le tableau soit vide (c'est le cas de base de notre
algorithme récursif ). À chacune de ces "itérations", nous ajoutons la valeur d'un des éléments du tableau au paramètre de la fonction
accumulator
, sans affecter l'
accumulator
variable globale. Dans ce cas, la
list
variables globales et l'
accumulator
restent inchangés; les mêmes valeurs y sont stockées avant et après l'appel de fonction.
Il convient de noter que pour implémenter un tel algorithme, vous pouvez utiliser la méthode de
reduce
tableau. Nous en parlerons ci-dessous.
En programmation, la tâche est répandue lorsqu'il est nécessaire, sur la base d'un certain modèle d'objet, de créer sa représentation finale. Imaginez que nous ayons une chaîne qui doit être convertie en une vue adaptée à une utilisation dans le cadre de l'URL menant à une certaine ressource.
Si nous résolvons ce problème en utilisant Ruby et en utilisant les principes de la POO, nous allons d'abord créer une classe, disons, en l'appelant
UrlSlugify
, puis créer une méthode pour cette classe
slugify!
qui est utilisé pour convertir la chaîne.
class UrlSlugify attr_reader :text def initialize(text) @text = text end def slugify! text.downcase! text.strip! text.gsub!(' ', '-') end end UrlSlugify.new(' I will be a url slug ').slugify! # "i-will-be-a-url-slug"
Nous avons implémenté l'algorithme, et c'est merveilleux. Nous voyons ici une approche impérative de la programmation, lorsque nous, en traitant la ligne, peignons chaque étape de sa transformation. À savoir, nous réduisons d'abord ses caractères en minuscules, puis supprimons les espaces inutiles, et enfin changeons les espaces restants sur le tiret.
Cependant, lors de cette transformation, une mutation de l'état du programme se produit.
Vous pouvez faire face au problème de mutation en composant des fonctions ou en enchaînant des appels de fonction. En d'autres termes, le résultat renvoyé par la fonction sera utilisé comme entrée pour la fonction suivante, et donc pour toutes les fonctions d'une chaîne. Dans ce cas, la chaîne d'origine ne changera pas.
let string = " I will be a url slug "; function slugify(string) { return string.toLowerCase() .trim() .split(" ") .join("-"); } slugify(string);
Ici, nous utilisons les fonctions suivantes, représentées en JavaScript par des méthodes de chaîne et de tableau standard:
toLowerCase
: convertit les caractères de chaîne en toLowerCase
.trim
: supprime les espaces du début et de la fin d'une ligne.split
: divise une chaîne en parties, plaçant les mots séparés par des espaces dans un tableau.join
: forme une chaîne de mots séparés par un tiret basé sur un tableau de mots.
Ces quatre fonctions vous permettent de créer une fonction pour convertir une chaîne qui ne change pas cette chaîne elle-même.
Transparence des liens
Créez une fonction
square()
qui renvoie le résultat de la multiplication d'un nombre par le même nombre:
function square(n) { return n * n; }
Il s'agit d'une fonction pure qui renvoie toujours, pour la même valeur d'entrée, la même valeur de sortie.
square(2);
Par exemple, quel que soit le nombre de numéros
2
sont transmis, cette fonction renvoie toujours le numéro
4
. En conséquence, il s'avère qu'un appel de la forme
square(2)
peut être remplacé par le numéro
4
. Cela signifie que notre fonction a la propriété de la transparence référentielle.
En général, nous pouvons dire que si une fonction renvoie invariablement le même résultat pour les mêmes valeurs d'entrée qui lui sont transmises, elle a une transparence référentielle.
Functions Fonctions pures + données immuables = transparence référentielle
En utilisant l'idée avancée dans le titre de cette section, vous pouvez mémoriser des fonctions. Supposons que nous ayons une fonction comme celle-ci:
function sum(a, b) { return a + b; }
Nous l'appelons comme ceci:
sum(3, sum(5, 8));
La
sum(5, 8)
appels
sum(5, 8)
donne toujours
13
. Par conséquent, l'appel ci-dessus peut être réécrit comme suit:
sum(3, 13);
Cette expression, à son tour, donne toujours
16
. En conséquence, il peut être remplacé par une constante numérique et
mémorisé .
Fonctionne comme des objets de première classe
L'idée de percevoir les fonctions comme des objets de première classe est que ces fonctions peuvent être considérées comme des valeurs et fonctionner avec elles comme des données. Les caractéristiques suivantes des fonctions peuvent être distinguées:
- Les références aux fonctions peuvent être stockées dans des constantes et des variables et, à travers elles, accéder aux fonctions.
- Les fonctions peuvent être transmises à d'autres fonctions en tant que paramètres.
- Les fonctions peuvent être renvoyées par d'autres fonctions.
Autrement dit, il s'agit de considérer les fonctions comme des valeurs et de les traiter comme des données. Avec cette approche, vous pouvez combiner différentes fonctions dans le processus de création de nouvelles fonctions qui implémentent de nouvelles fonctionnalités.
Imaginez que nous ayons une fonction qui ajoute deux valeurs numériques qui lui sont transmises, puis les multiplie par
2
et retourne ce qu'il s'est avéré:
function doubleSum(a, b) { return (a + b) * 2; }
Maintenant, nous écrivons une fonction qui soustrait la seconde de la première valeur numérique qui lui est passée, multiplie ce qui s'est passé par
2
et renvoie la valeur calculée:
function doubleSubtraction(a, b) { return (a - b) * 2; }
Ces fonctions ont une logique similaire, elles ne diffèrent que par le type d'opérations qu'elles effectuent avec les nombres qui leur sont transmis. Si nous pouvons considérer les fonctions comme des valeurs et les transmettre comme arguments à d'autres fonctions, cela signifie que nous pouvons créer une fonction qui accepte et utilise une autre fonction qui décrit les caractéristiques des calculs. Ces considérations nous permettent d'atteindre les constructions suivantes:
function sum(a, b) { return a + b; } function subtraction(a, b) { return a - b; } function doubleOperator(f, a, b) { return f(a, b) * 2; } doubleOperator(sum, 3, 1);
Comme vous pouvez le voir, la fonction
doubleOperator()
a maintenant un paramètre
f
, et la fonction qu'elle représente est utilisée pour traiter les paramètres
a
et
b
. En fait, les fonctions
sum()
et
substraction()
transmises à la fonction
doubleOperator()
vous permettent de contrôler le comportement de la fonction
doubleOperator()
, en le modifiant conformément à la logique implémentée.
Fonctions d'ordre supérieur
Parlant de fonctions d'ordre supérieur, nous entendons des fonctions caractérisées par au moins l'une des caractéristiques suivantes:
- Une fonction prend une autre fonction comme argument (il peut y avoir plusieurs de ces fonctions).
- La fonction renvoie une autre fonction à la suite de son travail.
Vous connaissez peut-être déjà les méthodes de tableau JS standard
filter()
,
map()
et
reduce()
. Parlons-en.
▍ Filtrer les tableaux et la méthode filter ()
Supposons que nous ayons une certaine collection d'éléments que nous voulons filtrer par un attribut des éléments de cette collection et former une nouvelle collection. La fonction
filter()
s'attend à recevoir un critère d'évaluation des éléments, sur la base duquel elle détermine s'il faut ou non inclure un élément dans la collection résultante. Ce critère est défini par la fonction qui lui est transmise, qui renvoie
true
si la fonction
filter()
doit inclure un élément dans la collection finale, sinon elle retourne
false
.
Imaginez que nous avons un tableau d'entiers et que nous voulons le filtrer en obtenant un nouveau tableau qui ne contient que des nombres pairs du tableau d'origine.
Approche impérative
Lors de l'application d'une approche impérative pour résoudre ce problème à l'aide de JavaScript, nous devons implémenter la séquence d'actions suivante:
- Créez un tableau vide pour les nouveaux éléments (appelons-le
evenNumbers
). - Itérer sur le tableau d'origine d'entiers (appelons cela des
numbers
). - Mettez les nombres pairs trouvés dans le tableau des
numbers
evenNumbers
tableau des numbers
evenNumbers
.
Voici à quoi ressemble l'implémentation de cet algorithme:
var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var evenNumbers = []; for (var i = 0; i < numbers.length; i++) { if (numbers[i] % 2 == 0) { evenNumbers.push(numbers[i]); } } console.log(evenNumbers);
De plus, nous pouvons écrire une fonction (appelons-la
even()
) qui, si le nombre est pair, renvoie
true
, et si elle est impaire, retourne
false
, puis la transmet à la méthode tableau
filter()
qui, en vérifiant avec elle, chaque élément du tableau , formera un nouveau tableau contenant uniquement des nombres pairs:
function even(number) { return number % 2 == 0; } let listOfNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; listOfNumbers.filter(even);
Voici, en passant, la solution à un problème intéressant concernant le
filtrage de tableaux , que j'ai terminé en travaillant sur des tâches de programmation fonctionnelle sur
Hacker Rank . À la condition du problème, il était nécessaire de filtrer un tableau d'entiers, affichant uniquement les éléments inférieurs à une valeur donnée de
x
.
Une solution impérative à ce problème en JavaScript pourrait ressembler à ceci:
var filterArray = function(x, coll) { var resultArray = []; for (var i = 0; i < coll.length; i++) { if (coll[i] < x) { resultArray.push(coll[i]); } } return resultArray; } console.log(filterArray(3, [10, 9, 8, 2, 7, 5, 1, 3, 0]));
L'essence de l'approche impérative est que nous décrivions la séquence d'actions exécutées par la fonction. À savoir, nous décrivons la recherche du tableau, en comparant l'élément actuel du tableau avec
x
et en plaçant cet élément dans le tableau
resultArray
s'il réussit le test.
Approche déclarative
Comment passer à une approche déclarative pour résoudre ce problème et l'utilisation correspondante de la méthode
filter()
, qui est une fonction d'ordre supérieur? Par exemple, cela pourrait ressembler à ceci:
function smaller(number) { return number < this; } function filterArray(x, listOfNumbers) { return listOfNumbers.filter(smaller, x); } let numbers = [10, 9, 8, 2, 7, 5, 1, 3, 0]; filterArray(3, numbers);
Vous trouverez peut-être inhabituel d'utiliser le
this
dans la fonction
smaller()
de cet exemple, mais il n'y a rien de compliqué ici. Le
this
-
this
est le deuxième argument de la méthode
filter()
. Dans notre exemple, il s'agit du nombre
3
représenté par le paramètre
x
de
filterArray()
. Ce numéro est indiqué par
this
.
La même approche peut être utilisée si le tableau contient des entités qui ont une structure assez complexe, par exemple des objets. Supposons que nous ayons un tableau stockant des objets contenant les noms des personnes représentées par la propriété
name
et des informations sur l'âge de ces personnes représentées par la propriété
age
. Voici à quoi ressemble un tableau:
let people = [ { name: "TK", age: 26 }, { name: "Kaio", age: 10 }, { name: "Kazumi", age: 30 } ];
Nous voulons filtrer ce tableau en sélectionnant uniquement les objets qui sont des personnes dont l'âge a dépassé
21
ans. Voici comment résoudre ce problème:
function olderThan21(person) { return person.age > 21; } function overAge(people) { return people.filter(olderThan21); } overAge(people);
Ici, nous avons un tableau avec des objets représentant des personnes. Nous vérifions les éléments de ce tableau à l'aide de la fonction
olderThan21()
. Dans ce cas, lors de la vérification, nous nous référons à la propriété
age
de chaque élément, vérifiant si la valeur de cette propriété dépasse
21
. Nous passons cette fonction à la méthode
filter()
, qui filtre le tableau.
▍ Traitement des éléments du tableau et de la méthode map ()
La méthode
map()
est utilisée pour convertir les éléments du tableau. Il applique la fonction passée à chaque élément du tableau, puis crée un nouveau tableau composé des éléments modifiés.
Continuons les expériences avec le tableau de
people
que vous connaissez déjà. Maintenant, nous n'allons pas filtrer ce tableau en fonction de la propriété des objets d'
age
. Nous devons créer sur sa base une liste de lignes de la forme
TK is 26 years old
. Dans cette approche, les lignes dans lesquelles les éléments se transforment seront construites selon le modèle
p.name is p.age years old
, où
p.name
et
p.age
sont les valeurs des propriétés correspondantes des éléments du tableau de
people
.
Une approche impérative pour résoudre ce problème en JavaScript ressemble à ceci:
var people = [ { name: "TK", age: 26 }, { name: "Kaio", age: 10 }, { name: "Kazumi", age: 30 } ]; var peopleSentences = []; for (var i = 0; i < people.length; i++) { var sentence = people[i].name + " is " + people[i].age + " years old"; peopleSentences.push(sentence); } console.log(peopleSentences);
Si vous recourez à une approche déclarative, vous obtenez ce qui suit:
function makeSentence(person) { return `${person.name} is ${person.age} years old`; } function peopleSentences(people) { return people.map(makeSentence); } peopleSentences(people);
En fait, l'idée principale ici est que vous devez faire quelque chose avec chaque élément du tableau d'origine, puis le placer dans un nouveau tableau.
Voici une autre tâche avec le Hacker Rank, qui est dédiée à la
mise à
jour de la liste . À savoir, nous parlons de changer les valeurs des éléments d'un tableau numérique existant en leurs valeurs absolues. Ainsi, par exemple, lors du traitement d'un tableau
[1, 2, 3, -4, 5]
il prendra la forme
[1, 2, 3, 4, 5]
car la valeur absolue de
-4
est
4
.
Voici un exemple de solution simple à ce problème, lorsque nous parcourons un tableau et modifions les valeurs de ses éléments en leurs valeurs absolues.
var values = [1, 2, 3, -4, 5]; for (var i = 0; i < values.length; i++) { values[i] = Math.abs(values[i]); } console.log(values);
Ici, pour convertir les valeurs des éléments du tableau, la méthode
Math.abs()
est utilisée, les éléments modifiés sont écrits au même endroit où ils étaient avant la conversion.
.
, , , . . , , , .
, ,
map()
. ?
,
abs()
, , .
Math.abs(-1);
, , .
, ,
Math.abs()
map()
. , ?
map()
. :
let values = [1, 2, 3, -4, 5]; function updateListMap(values) { return values.map(Math.abs); } updateListMap(values);
, , , , , .
▍ reduce()
reduce()
.
. , -.
Product 1
,
Product 2
,
Product 3
Product 4
. .
, . Par exemple, cela pourrait ressembler à ceci:
var orders = [ { productTitle: "Product 1", amount: 10 }, { productTitle: "Product 2", amount: 30 }, { productTitle: "Product 3", amount: 20 }, { productTitle: "Product 4", amount: 60 } ]; var totalAmount = 0; for (var i = 0; i < orders.length; i++) { totalAmount += orders[i].amount; } console.log(totalAmount);
reduce()
, (
sumAmount()
), ,
reduce()
:
let shoppingCart = [ { productTitle: "Product 1", amount: 10 }, { productTitle: "Product 2", amount: 30 }, { productTitle: "Product 3", amount: 20 }, { productTitle: "Product 4", amount: 60 } ]; const sumAmount = (currentTotalAmount, order) => currentTotalAmount + order.amount; function getTotalAmount(shoppingCart) { return shoppingCart.reduce(sumAmount, 0); } getTotalAmount(shoppingCart);
shoppingCart
, ,
sumAmount()
, (
order
,
amount
), —
currentTotalAmount
.
reduce()
,
getTotalAmount()
,
sumAmount()
,
0
.
map()
reduce()
. «»? ,
map()
shoppingCart
,
amount
,
reduce()
sumAmount()
. :
const getAmount = (order) => order.amount; const sumAmount = (acc, amount) => acc + amount; function getTotalAmount(shoppingCart) { return shoppingCart .map(getAmount) .reduce(sumAmount, 0); } getTotalAmount(shoppingCart);
getAmount()
amount
.
map()
, , ,
[10, 30, 20, 60]
. ,
reduce()
, .
▍ filter(), map() reduce()
, ,
filter()
,
map()
reduce()
. , , .
-. , :
let shoppingCart = [ { productTitle: "Functional Programming", type: "books", amount: 10 }, { productTitle: "Kindle", type: "eletronics", amount: 30 }, { productTitle: "Shoes", type: "fashion", amount: 20 }, { productTitle: "Clean Code", type: "books", amount: 60 } ]
. :
, :
let shoppingCart = [ { productTitle: "Functional Programming", type: "books", amount: 10 }, { productTitle: "Kindle", type: "eletronics", amount: 30 }, { productTitle: "Shoes", type: "fashion", amount: 20 }, { productTitle: "Clean Code", type: "books", amount: 60 } ] const byBooks = (order) => order.type == "books"; const getAmount = (order) => order.amount; const sumAmount = (acc, amount) => acc + amount; function getTotalAmount(shoppingCart) { return shoppingCart .filter(byBooks) .map(getAmount) .reduce(sumAmount, 0); } getTotalAmount(shoppingCart);
Résumé
JavaScript-. , .
Chers lecteurs! ?
