成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【譯】JavaScript 中的函數(shù)式編程原理

zhigoo / 1320人閱讀

摘要:在這篇文章中,我將通過中的大量代碼示例向您詳細(xì)介紹函數(shù)式編程和一些重要概念。注意在函數(shù)式編程中不鼓勵(lì)可變性。純函數(shù)是穩(wěn)定,一致并且可預(yù)測的。

原文:Functional Programming Principles in Javascript
作者:TK
譯者:博軒

經(jīng)過很長一段時(shí)間的學(xué)習(xí)和面向?qū)ο缶幊痰墓ぷ?,我退后一步,開始思考系統(tǒng)的復(fù)雜性。

“復(fù)雜性是任何使軟件難以理解或修改的東西。” -  John Outerhout

做了一些研究,我發(fā)現(xiàn)了函數(shù)式編程概念,如不變性和純函數(shù)。 這些概念使你能夠構(gòu)建無副作用的功能,而函數(shù)式編程的一些優(yōu)點(diǎn),也使得系統(tǒng)變得更加容易維護(hù)。

在這篇文章中,我將通過 JavaScript 中的大量代碼示例向您詳細(xì)介紹函數(shù)式編程和一些重要概念。

什么是函數(shù)式編程?

維基百科:Functional programming

函數(shù)式編程是一種編程范式,一種構(gòu)建計(jì)算機(jī)程序結(jié)構(gòu)和元素的方式,將計(jì)算視為數(shù)學(xué)函數(shù)的評(píng)估并避免改變狀態(tài)和可變數(shù)據(jù) -- 維基百科
純函數(shù)

當(dāng)我們想要理解函數(shù)式編程時(shí),我們學(xué)到的第一個(gè)基本概念是純函數(shù)。 那么我們?cè)趺粗篮瘮?shù)是否純粹呢? 這是一個(gè)非常嚴(yán)格的純度定義:

如果給出相同的參數(shù),它返回相同的結(jié)果(它也稱為確定性

它不會(huì)引起任何可觀察到的副作用

如果給出相同的參數(shù),它返回相同的結(jié)果

我們想要實(shí)現(xiàn)一個(gè)計(jì)算圓的面積的函數(shù)。 不純的函數(shù)將接收半徑:radius 作為參數(shù),然后計(jì)算 radius * radius * PI :

const PI = 3.14;

const calculateArea = (radius) => radius * radius * PI;

calculateArea(10); // returns 314

為什么這是一個(gè)不純的功能? 僅僅因?yàn)樗褂玫氖俏醋鳛閰?shù)傳遞給函數(shù)的全局對(duì)象。

想象一下,數(shù)學(xué)家認(rèn)為 PI 值實(shí)際上是 42, 并且改變了全局對(duì)象的值。

不純的函數(shù)現(xiàn)在將導(dǎo)致 10 * 10 * 42 = 4200 .對(duì)于相同的參數(shù)(radius= 10),我們得到不同的結(jié)果。

我們來解決它吧!

const PI = 3.14;

const calculateArea = (radius, pi) => radius * radius * pi;

calculateArea(10, PI); // returns 314

現(xiàn)在我們將 PI 的值作為參數(shù)傳遞給函數(shù)。 所以現(xiàn)在我們只是訪問傳遞給函數(shù)的參數(shù)。 沒有外部對(duì)象(參數(shù))。

對(duì)于參數(shù) radius = 10PI = 3.14,我們將始終具有相同的結(jié)果:314

對(duì)于參數(shù) radius = 10PI = 42,我們將始終具有相同的結(jié)果:4200

讀取文件 (Node.js)

如果我們的函數(shù)讀取外部文件,它也不是純函數(shù) - 文件的內(nèi)容可以更改:

const fs = require("fs");
const charactersCounter = (text) => `Character count: ${text.length}`;

function analyzeFile(filepath) {
    let fileContent = fs.readFileSync(filepath);
    return charactersCounter(fileContent);
}
生成隨機(jī)數(shù)

任何依賴于隨機(jī)數(shù)生成器的函數(shù)都不可能是純函數(shù):

function yearEndEvaluation() {
    if (Math.random() > 0.5) {
        return "You get a raise!";
    } else {
        return "Better luck next year!";
    }
}
它不會(huì)引起任何可觀察到的副作用

什么是可觀察副作用呢?其中一種示例,就是在函數(shù)內(nèi)修改全局的對(duì)象,或者參數(shù)。

現(xiàn)在我們要實(shí)現(xiàn)一個(gè)函數(shù),來接收一個(gè)整數(shù)值并返回增加 1 的值。

let counter = 1;

function increaseCounter(value) {
  counter = value + 1;
}

increaseCounter(counter);
console.log(counter); // 2

我們首先定義了變量 counter 。 然后使用不純的函數(shù)接收該值并重新為 counter 賦值,使其值增加 1 。

注意:在函數(shù)式編程中不鼓勵(lì)可變性。

上面的例子中,我們修改了全局對(duì)象。 但是我們?nèi)绾尾拍茏尯瘮?shù)變得純凈呢? 只需返回增加 1 的值。

let counter = 1;

const increaseCounter = (value) => value + 1;

increaseCounter(counter); // 2
console.log(counter); // 1

可以看到我們的純函數(shù) increaseCounter 返回 2 ,但是 counter 還保持之前的值。該函數(shù)會(huì)使返回的數(shù)字遞增,而且不更改變量的值。

如果我們遵循這兩個(gè)簡單的規(guī)則,就會(huì)使我們的程序更加容易理解。每個(gè)功能都是孤立的,無法影響到我們的系統(tǒng)。

純函數(shù)是穩(wěn)定,一致并且可預(yù)測的。給定相同的參數(shù),純函數(shù)將始終返回相同的結(jié)果。我們不需要考慮,相同的參數(shù)會(huì)產(chǎn)生不同的結(jié)果,因?yàn)樗肋h(yuǎn)不會(huì)發(fā)生。

純函數(shù)的好處 容易測試

純函數(shù)的代碼更加容易測試。我們不需要模擬任何執(zhí)行的上下文。我們可以使用不同的上下文對(duì)純函數(shù)進(jìn)行單元測試:

給定參數(shù) A -> 期望函數(shù)返回 B

給定參數(shù) C -> 期望函數(shù)返回 D

一個(gè)簡單的例子,函數(shù)接收一個(gè)數(shù)字集合,并期望數(shù)字集合每個(gè)元素遞增。

let list = [1, 2, 3, 4, 5];

const incrementNumbers = (list) => list.map(number => number + 1);

我們接收到數(shù)字?jǐn)?shù)組,使用 map 遞增每個(gè)數(shù)字,并返回一個(gè)新的遞增數(shù)字列表。

incrementNumbers(list); // [2, 3, 4, 5, 6]

對(duì)于輸入 [1, 2, 3, 4, 5],預(yù)期輸出將是 [2, 3, 4, 5, 6]。

不變性
隨著時(shí)間的推移不變,或無法改變

當(dāng)數(shù)據(jù)具有不可變性時(shí),它的狀態(tài)在創(chuàng)建之后,就不能改變了。你不能去更改一個(gè)不可變的對(duì)象,但是你可以使用新值去創(chuàng)建一個(gè)新的對(duì)象。

JavaScript 中,我們常使用 for 循環(huán)。下面這個(gè) for 循環(huán)有一些可變的變量。

var values = [1, 2, 3, 4, 5];
var sumOfValues = 0;

for (var i = 0; i < values.length; i++) {
  sumOfValues += values[i];
}

sumOfValues // 15

對(duì)于每次迭代,我們都在改變變量 isumOfValues 的狀態(tài)。但是我們要如何處理迭代中的可變性?使用遞歸

let list = [1, 2, 3, 4, 5];
let accumulator = 0;

function sum(list, accumulator) {
    if (list.length == 0) {
        return accumulator;
    }

    // 移除數(shù)組第一項(xiàng),并做累加
    return sum(list.slice(1), accumulator + list[0]);
}

sum(list, accumulator); // 15
list; // [1, 2, 3, 4, 5]
accumulator; // 0

所以這里我們有 sum 函數(shù)接收數(shù)值向量。 該函數(shù)調(diào)用自身,直到我們將列表清空。 對(duì)于每個(gè)“迭代”,我們會(huì)將該值添加到總累加器。

使用遞歸,我們可以保持變量的不可變性。 列表和累加器變量不會(huì)更改,會(huì)保持相同的值。

注意:我們可以使用reduce來實(shí)現(xiàn)這個(gè)功能。 我們將在高階函數(shù)主題中介紹這個(gè)話題。

構(gòu)建對(duì)象的最終狀態(tài)也很常見。想象一下,我們有一個(gè)字符串,我們想將這個(gè)字符串轉(zhuǎn)換為 url slug。

Ruby 中的面向?qū)ο缶幊讨?,我們將?chuàng)建一個(gè)類,比方說,UrlSlugify。 這個(gè)類將有一個(gè) slugify 方法將字符串輸入轉(zhuǎn)換為 url slug

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"

他已經(jīng)實(shí)現(xiàn)了?。?b>It’s implemented!)

這里我們使用命令式編程,準(zhǔn)確的說明我們想要在 函數(shù)實(shí)現(xiàn)的過程中(slugify)每一步要做什么:首先是轉(zhuǎn)換成小寫,然后移除無用的空格,最后用連字符替換剩余的空格。

但是,在這個(gè)過程中,函數(shù)改變了輸入的參數(shù)。

我們可以通過執(zhí)行函數(shù)組合或函數(shù)鏈來處理這種變異。 換句話說,函數(shù)的結(jié)果將用作下一個(gè)函數(shù)的輸入,而不修改原始輸入字符串。

let string = " I will be a url slug   ";

function slugify(string) {
  return string.toLowerCase()
    .trim()
    .split(" ")
    .join("-");
}

slugify(string); // i-will-be-a-url-slug

這里我們:

toLowerCase:將字符串轉(zhuǎn)換為全部小寫

trim:從字符串的兩端刪除空格

splitjoin :用給定字符串中的替換替換所有匹配實(shí)例

我們將所有這四個(gè)功能結(jié)合起來,就可以實(shí)現(xiàn) slugify 的功能了。

參考透明度

維基百科:Referential transparency

如果表達(dá)式可以替換為其相應(yīng)的值而不更改程序的行為,則該表達(dá)式稱為引用透明。這要求表達(dá)式是純粹的,也就是說相同輸入的表達(dá)式值必須相同,并且其評(píng)估必須沒有副作用。-- 維基百科

讓我們實(shí)現(xiàn)一個(gè)計(jì)算平方的方法:

const square = (n) => n * n;

在給定相同輸入的情況下,此純函數(shù)將始終具有相同的輸出。

square(2); // 4
square(2); // 4
square(2); // 4
// ...

2 傳遞給 square 方法將始終返回 4。所以,現(xiàn)在我們可以使用 4 來替換 square(2)。我們的函數(shù)是引用透明的。

基本上,如果函數(shù)對(duì)同一輸入始終產(chǎn)生相同的結(jié)果,則引用透明。

pure functions + immutable data = referential transparency

純函數(shù) + 不可變數(shù)據(jù) = 參照透明度

有了這個(gè)概念,我們可以做一件很 cool 的事情,就是使這個(gè)函數(shù)擁有記憶(memoize)。
想象一下我們擁有這樣一個(gè)函數(shù):

const sum = (a, b) => a + b;

我們用這些參數(shù)調(diào)用它:

sum(3, sum(5, 8));

sum(5, 8) 等于 13。這個(gè)函數(shù)總是返回 13。因此,我們可以這樣做:

sum(3, 13);

這個(gè)表達(dá)式總是會(huì)返回 16 。我們可以用一個(gè)數(shù)值常量替換整個(gè)表達(dá)式,并記住它。

這里推薦一篇淘寶FED關(guān)于 memoize 的文章:性能優(yōu)化:memoization
函數(shù)是一等公民

函數(shù)作為一等公民,意味著函數(shù)也可以視為值處理,并當(dāng)做數(shù)據(jù)來使用。

函數(shù)作為一等公民有如下特性:

可以當(dāng)做常量,或者變量來引用

將函數(shù)當(dāng)做參數(shù)傳遞給其他函數(shù)

將函數(shù)作為其他函數(shù)的返回值

我們的想法是函數(shù)視為值并將它們作為參數(shù)傳遞。 這樣我們就可以組合不同的函數(shù)來創(chuàng)建具有新行為的新函數(shù)。

想象一下,我們有一個(gè)函數(shù)可以將兩個(gè)值相加,然后將該值加倍:

const doubleSum = (a, b) => (a + b) * 2;

現(xiàn)在是一個(gè),將兩值相減,并返回該值加倍的函數(shù):

const doubleSubtraction = (a, b) => (a - b) * 2;

這些函數(shù)具有相似的邏輯,但是計(jì)算時(shí)的運(yùn)算符不同。 如果我們可以將函數(shù)視為值并將它們作為參數(shù)傳遞,我們可以構(gòu)建一個(gè)函數(shù)來接收運(yùn)算符函數(shù)并在函數(shù)中使用它。

const sum = (a, b) => a + b;
const subtraction = (a, b) => a - b;

const doubleOperator = (f, a, b) => f(a, b) * 2;

doubleOperator(sum, 3, 1); // 8
doubleOperator(subtraction, 3, 1); // 4

現(xiàn)在我們有一個(gè)函數(shù)參數(shù):f,并用它來處理 ab 。 我們傳遞了 sumsubtraction 函數(shù)以使用 doubleOperator 函數(shù)進(jìn)行組合并創(chuàng)建一個(gè)新行為。

高階函數(shù)

維基百科:Higher-order function

當(dāng)我們談?wù)?strong>高階函數(shù)時(shí),通常是指一個(gè)函數(shù)同時(shí)具有:

將一個(gè)或多個(gè)函數(shù)作為參數(shù),或

返回一個(gè)函數(shù)作為結(jié)果

我們上面實(shí)現(xiàn)的 doubleOperator 函數(shù)是一個(gè)高階函數(shù),因?yàn)樗鼘⒁粋€(gè)運(yùn)算符函數(shù)作為參數(shù)并使用它。

您可能已經(jīng)聽說過 filter,mapreduce 。 我們來看看這些。

Filter

給定一個(gè)集合,我們希望按照屬性進(jìn)行過濾。filter 函數(shù)需要 true 或者 false 值來確定元素是否應(yīng)該包含在結(jié)果集合中?;旧?,如果回調(diào)表達(dá)式返回的是 truefilter 函數(shù)返回的結(jié)果會(huì)包含該元素。否則,就不會(huì)包含該元素。

一個(gè)簡單的例子是當(dāng)我們有一個(gè)整數(shù)集合時(shí),我們只想要過濾偶數(shù)。

命令式編程

使用 JavaScript 來實(shí)現(xiàn)時(shí),需要如下操作:

創(chuàng)建一個(gè)空數(shù)組 evenNumbers

迭代數(shù)字?jǐn)?shù)組

將偶數(shù)推到 evenNumbers 數(shù)組

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); // (6) [0, 2, 4, 6, 8, 10]

我們還可以使用 filter 高階函數(shù)來接收 even 函數(shù),并返回偶數(shù)列表:

const even = n => n % 2 == 0;
const listOfNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
listOfNumbers.filter(even); // [0, 2, 4, 6, 8, 10]

我在Hacker Rank FP上解決的一個(gè)有趣問題是Filter Array問題。 問題的想法是過濾給定的整數(shù)數(shù)組,并僅輸出那些小于指定值X的值。

針對(duì)此問題,命令式JavaScript解決方案如下:

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])); // (3) [2, 1, 0]

我們的函數(shù)會(huì)做如下的事情 - 迭代集合,將集合當(dāng)前項(xiàng)與 x 進(jìn)行比較,如果它符合條件,則將此元素推送到 resultArray。

聲明式編程

但我們想要一種更具聲明性的方法來解決這個(gè)問題,并使用過濾器高階函數(shù)。

聲明式 JavaScript 解決方案將是這樣的:

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); // [2, 1, 0]

smaller 函數(shù)中使用 this 首先看起來有點(diǎn)奇怪,但很容易理解。

this 將作為第二個(gè)參數(shù)傳給 filter 方法。在這個(gè)示例中,3x)代表 this。

這樣的操作也可以用于集合。 想象一下,我們有一個(gè)人物集合,包含了 name、 age 屬性。

let people = [
  { name: "TK", age: 26 },
  { name: "Kaio", age: 10 },
  { name: "Kazumi", age: 30 }
];

我們希望僅過濾指定年齡值的人,在此示例中,年齡超過18歲的人。

const olderThan18 = person => person.age > 18;
const overAge = people => people.filter(olderThan18);
overAge(people); // [{ name: "TK", age: 26 }, { name: "Kazumi", age: 30 }]

代碼摘要:

我們有一份人員名單(姓名和年齡)。

我們有一個(gè)函數(shù) oldThan18。在這種情況下,對(duì)于 people 數(shù)組中的每個(gè)人,我們想要訪問年齡并查看它是否超過 18 歲。

我們根據(jù)此功能過濾所有人。

Map

map 的概念是轉(zhuǎn)換一個(gè)集合。

map 方法會(huì)將集合傳入函數(shù),并根據(jù)返回的值構(gòu)建新集合。

讓我們使用剛才的 people 集合。我們現(xiàn)在不想過濾年齡了。我們只想得到一個(gè)列表,元素就像:TK is 26 years old。所以最后的字符串可能是 :name is:age years old 其中 :name:agepeople 集合中每個(gè)元素的屬性。

下面是使用命令式 JavaScript 編碼的示例:

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); // ["TK is 26 years old", "Kaio is 10 years old", "Kazumi is 30 years old"]

下面是使用聲明式 JavaScript 編碼的示例:

const makeSentence = (person) => `${person.name} is ${person.age} years old`;

const peopleSentences = (people) => people.map(makeSentence);
  
peopleSentences(people);
// ["TK is 26 years old", "Kaio is 10 years old", "Kazumi is 30 years old"]

要做的事情是將給定數(shù)組轉(zhuǎn)換為新數(shù)組。

另一個(gè)有趣的 Hacker Rank 問題是更新列表問題。 我們只想用它們的絕對(duì)值更新給定數(shù)組的值。

例如,輸入 [1,2,3-4,5] 需要輸出為 [1,2,3,4,5] 。 -4 的絕對(duì)值是 4。

一種簡單的解決方案是將每個(gè)集合的值進(jìn)行就地更新 (in-place)。

var values = [1, 2, 3, -4, 5];

for (var i = 0; i < values.length; i++) {
  values[i] = Math.abs(values[i]);
}

console.log(values); // [1, 2, 3, 4, 5]

我們使用 Math.abs 函數(shù)將值轉(zhuǎn)換為其絕對(duì)值,并進(jìn)行就地更新。

這不是一個(gè)函數(shù)式的解決方案。

首先,我們了解了不變性。 我們知道不可變性對(duì)于使我們的函數(shù)更加一致和可預(yù)測非常重要。 我們的想法是建立一個(gè)具有所有絕對(duì)值的新集合。

第二,為什么不在這里使用 map轉(zhuǎn)換所有數(shù)據(jù)?

我的第一個(gè)想法是測試 Math.abs 函數(shù)只處理一個(gè)值。

Math.abs(-1); // 1
Math.abs(1); // 1
Math.abs(-2); // 2
Math.abs(2); // 2

我們希望將每個(gè)值轉(zhuǎn)換為正值(絕對(duì)值)。

現(xiàn)在我們知道如何對(duì)一個(gè)值進(jìn)行取絕對(duì)值的操作,我們可以將這個(gè)函數(shù)通過參數(shù)的方式傳遞給 map 。你還記得高階函數(shù)可以接收函數(shù)作為參數(shù)并使用它嗎? 是的,map 可以。

let values = [1, 2, 3, -4, 5];

const updateListMap = (values) => values.map(Math.abs);

updateListMap(values); // [1, 2, 3, 4, 5]

Wow,鵝妹子嚶!

Reduce

reduce 函數(shù)的概念是,接收一個(gè)函數(shù)和一個(gè)集合,然后組合他們來創(chuàng)建返回值。

一個(gè)常見的例子是獲得訂單的總金額。想象一下,你正在一個(gè)購物網(wǎng)站購物。你增加了 Product 1Product 2,Product 3Product 4 到你的購物車?,F(xiàn)在我們要計(jì)算購物車的總金額。

使用命令式編程的方式,我們將迭代訂單列表并將每個(gè)產(chǎn)品金額與總金額相加。

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); // 120

使用 reduce ,我們可以創(chuàng)建一個(gè)用來處理累加的函數(shù),并將其作為參數(shù)傳給 reduce 函數(shù)。

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;

const getTotalAmount = (cart) => cart.reduce(sumAmount, 0);

getTotalAmount(shoppingCart); // 120

這里我們有 shoppingCart,sumAmount函數(shù)接收當(dāng)前的 currentTotalAmount ,對(duì)所有訂單進(jìn)行累加。

getTotalAmount 函數(shù)會(huì)接收 sumAmount 函數(shù) 從 0 開始累加購物車的值。

獲得總金額的另一種方法是組合使用 mapreduce。 那是什么意思? 我們可以使用 mapshoppingCart 轉(zhuǎn)換為 amount 值的集合,然后只使用 reduce 函數(shù)和 sumAmount 函數(shù)。

const getAmount = (order) => order.amount;
const sumAmount = (acc, amount) => acc + amount;

function getTotalAmount(shoppingCart) {
  return shoppingCart
    .map(getAmount)
    .reduce(sumAmount, 0);
}

getTotalAmount(shoppingCart); // 120

getAmount 函數(shù)接收產(chǎn)品對(duì)象并僅返回金額值。 所以我們這里有 [10,30,20,60] 。 然后,通過 reduce 累加所有金額。Nice~

我們看了每個(gè)高階函數(shù)的工作原理。 我想向您展示一個(gè)示例,說明如何在一個(gè)簡單的示例中組合所有三個(gè)函數(shù)。

還是購物車,想象一下在我們的訂單中有一個(gè)產(chǎn)品列表:

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 }
]

我們想要購物車中所有圖書的總金額。 就那么簡單, 需要怎樣編寫算法?

使用 filter 函數(shù)過濾書籍類型

使用 map 函數(shù)將購物車轉(zhuǎn)換為數(shù)量的集合

使用 reduce 函數(shù)累加所有項(xiàng)目

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); // 70

Done!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104050.html

相關(guān)文章

  • 】this 是什么?JavaScript 對(duì)象的內(nèi)部工作原理

    摘要:關(guān)鍵字會(huì)實(shí)例化一個(gè)新的對(duì)象實(shí)例,并在執(zhí)行構(gòu)造函數(shù)時(shí)將指向該實(shí)例。原文鏈接譯是什么對(duì)象的內(nèi)部工作原理 原文鏈接:What is this? The Inner Workings of JavaScript Objects (需要梯子) 原文作者:Eric Elliott 譯文永久鏈接:【譯】什么是 this?JavaScript 對(duì)象的內(nèi)部工作原理 譯者:士心 翻譯目的:函數(shù)動(dòng)...

    Hwg 評(píng)論0 收藏0
  • 函數(shù)的React

    摘要:高階組件和高階函數(shù)高階組件是編程中的常見模式。您可以將上面例子中的高階函數(shù)用函數(shù)的方式來重新整理如你所見,這就像是一個(gè)高階函數(shù),這個(gè)函數(shù)接受一個(gè)函數(shù),返回一個(gè)新的元素。函數(shù)式編程范例旨在避免在應(yīng)用程序中使用狀態(tài)。 原文:The functional side of React作者:Andrea Chiarelli譯者:博軒 React 是現(xiàn)在最流行的 JavaScript 庫之一。使用...

    gnehc 評(píng)論0 收藏0
  • 正在失業(yè)中的《課多周刊》(第3期)

    摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時(shí)一運(yùn)維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大的...

    robin 評(píng)論0 收藏0
  • 正在失業(yè)中的《課多周刊》(第3期)

    摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時(shí)一運(yùn)維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大的...

    Joyven 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<