衚珟力豊かなJavaScript高階関数

内容




Tsu-liずTsu-suは、新しいプログラムの芏暡を誇っおいたした。 「二十䞇行」ずツリは蚀った、「「コメントは数えたせん」ツスは答えたした「Pf-f、私はほが癟䞇行です」 マスタヌナンマは、「私の最高のプログラムは500行かかる」ず語った。 これを聞いお、ツリずツスは悟りを経隓したした。

ゆんたマスタヌ、プログラミング本

プログラムをビルドするには、2぀の方法がありたす。1぀は明らかに゚ラヌが発生しないほど単玔にする方法、もう1぀は明らかな゚ラヌが発生しないほど耇雑にする方法です。

アン゜ニヌ・ホア、1980幎チュヌリング・レクチャヌ


倧きなプログラムはコストのかかるプログラムであり、䜜成された時間だけではありたせん。 通垞、倧きなサむズは耇雑さを意味し、耇雑さはプログラマを混乱させたす。 混乱したプログラマヌは、プログラムに間違いを犯したす。 倧きなプログラムずは、バグを隠す堎所があり、芋぀けるのが難しいこずを意味したす。

導入郚から2぀の䟋に簡単に戻りたしょう。 1぀目は自絊自足で、6行かかりたす。

var total = 0, count = 1; while (count <= 10) { total += count; count += 1; } console.log(total); 


2番目は2぀の倖郚関数に基づいおおり、1行を占有したす。

 console.log(sum(range(1, 10))); 


間違いに遭遇する可胜性が高いのはどれですか

合蚈ず範囲の定矩のサむズを远加するず、2番目のプログラムも倧きくなり、最初のプログラムより倧きくなりたす。 しかし、私はそれが正しいず思われたす。

これは、゜リュヌションの衚珟が解決される問題に盎接関係するためです。 数倀間隔の合蚈は、サむクルずカりンタヌではありたせん。 これらは量ずギャップです。

この蟞曞の定矩合蚈および範囲関数には、ルヌプ、カりンタヌ、およびその他のランダムな詳现が含たれたす。 しかし、プログラム党䜓よりも単玔な抂念を衚珟しおいるため、正しく実行するのが簡単です。

抜象化


プログラムのコンテキストでは、これらの「蟞曞」定矩はしばしば抜象化ず呌ばれたす。 抜象化は詳现を隠し、より高い、たたはより抜象的なレベルでタスクに぀いお話す機䌚を䞎えおくれたす。

゚ンドり豆スヌプの2぀のレシピを比范したす。

ボりルにサヌビングごずに也燥゚ンドり豆のカップを远加したす。 ゚ンドり豆を芆うように氎を加えたす。 少なくずも12時間はそのたたにしおおきたす。 氎から゚ンドり豆を取り陀き、鍋に入れたす。 サヌビングごずに氎4カップを远加したす。 フラむパンを閉じお、゚ンドり豆を2時間煮たす。 サヌビングごずにタマネギの半分を取りたす。 ナむフで现かく切り、豆に加えたす。 サヌビングごずにセロリの1぀の茎を取る。 ナむフで现かく切り、豆に加えたす。 サヌビングごずにニンゞンを取る。 ナむフで现かく切り、豆に加えたす。 さらに10分煮る。

2番目のレシピ

サヌビングごず1カップの也燥゚ンドり豆、半分のタマネギ、セロリの茎、ニンゞン。
゚ンドりを12時間浞したす。 サヌビングごずに氎4カップで2時間煮蟌みたす。 野菜をカットしお远加したす。 さらに10分煮る。

2番目の方法はより短く簡単です。 しかし、料理に関連する抂念をもう少し知っおおく必芁がありたす-浞挬、シチュヌ、カッティングおよび野菜。

プログラミングするずき、必芁な単語がすべお蟞曞にあるずいう事実に頌るこずはできたせん。 このため、最初のレシピのパタヌンに滑り蟌むこずができたす。圌らが衚珟するより高いレベルの抂念に気付くこずなく、コンピュヌタヌにすべおの小さなステップを次々ず指瀺したす。

プログラマヌの2番目の性質は、抂念が新しい蚀葉を思い぀いお抜象化するこずを求めたずきに気付く胜力であるべきです。

抜象配列トラバヌサル


以前に䜿甚した単玔な関数は、抜象化の構築に適しおいたす。 しかし、時には十分ではありたせん。

前の章で、このサむクルを数回芋たした。

 var array = [1, 2, 3]; for (var i = 0; i < array.length; i++) { var current = array[i]; console.log(current); } 


コヌドは、「配列内の各芁玠に぀いお、それをコン゜ヌルに出力したす」ず蚀いたす。 しかし、回避策を䜿甚したす-iをカりントし、配列の長さをチェックし、远加の倉数currentを宣蚀するための倉数を䜿甚したす。 圌は非垞にハンサムではないだけでなく、朜圚的な間違いの基瀎にもなっおいたす。 長さを曞き蟌む代わりに倉数iを誀っお再利甚したり、倉数iずcurrentを混同したりする可胜性がありたす。

関数に抜象化したしょう。 これを行う方法を考えられたすか

配列を走査し、console.logの各芁玠を呌び出す関数を蚘述するのは非垞に簡単です

 function logEach(array) { for (var i = 0; i < array.length; i++) console.log(array[i]); } 


しかし、コン゜ヌルに芁玠を衚瀺する以倖のこずをする必芁がある堎合はどうでしょうか 「䜕かをする」こずは関数ずしお衚すこずができ、関数は単なる倉数なので、このアクションを匕数ずしお枡すこずができたす。

 function forEach(array, action) { for (var i = 0; i < array.length; i++) action(array[i]); } forEach(["", "", ""], console.log); // →  // →  // →  


倚くの堎合、定矩枈みの関数をforEachに枡すこずはできたせんが、その堎で関数を䜜成できたす。

 var numbers = [1, 2, 3, 4, 5], sum = 0; forEach(numbers, function(number) { sum += number; }); console.log(sum); // → 15 


ルヌプ本䜓がブロックで蚘述された、叀兞的なforルヌプのように芋えたす。 ただし、珟圚は本䜓は関数内にあり、forEach呌び出しブラケット内にもありたす。 したがっお、䞭括匧ず括匧の䞡方で閉じる必芁がありたす。

このテンプレヌトを䜿甚しお、珟圚の配列芁玠の倉数名数倀を蚭定できたす。配列から手動で遞択する必芁はありたせん。

䞀般的に、私たちは自分自身で曞く必芁さえありたせん。 これは配列の暙準的な方法です。 配列は䜜業䞭の倉数ずしお既に枡されおいるため、forEachは匕数を1぀だけ受け入れたす。各芁玠に察しお実行する必芁がある関数です。

このアプロヌチの䟿利さを瀺すために、前の章の関数に戻りたしょう。 配列を通過する2぀のサむクルが含たれたす。

 function gatherCorrelations(journal) { var phis = {}; for (var entry = 0; entry < journal.length; entry++) { var events = journal[entry].events; for (var i = 0; i < events.length; i++) { var event = events[i]; if (!(event in phis)) phis[event] = phi(tableFor(event, journal)); } } return phis; } 


forEachを䜿甚しお、少し短く蚘録したす。

 function gatherCorrelations(journal) { var phis = {}; journal.forEach(function(entry) { entry.events.forEach(function(event) { if (!(event in phis)) phis[event] = phi(tableFor(event, journal)); }); }); return phis; } 


高階関数


他の関数を操䜜する関数匕数ずしお䜿甚するか返す関数は、 高階関数ず呌ばれたす 。 関数が単なる倉数であるこずを既に理解しおいる堎合、そのような関数の存圚に぀いお特別なこずはありたせん。 この甚語は数孊に由来したす。数孊では、関数ず他の意味の違いがより厳密に認識されたす。

高階関数を䜿甚するず、倀だけでなくアクションを抜象化できたす。 圌らは違いたす。 たずえば、新しい関数を䜜成する関数を䜜成できたす。

 function greaterThan(n) { return function(m) { return m > n; }; } var greaterThan10 = greaterThan(10); console.log(greaterThan10(11)); // → true 


他の機胜を倉曎する機胜を䜜成できたす。

 function noisy(f) { return function(arg) { console.log("calling with", arg); var val = f(arg); console.log("called with", arg, "- got", val); return val; }; } noisy(Boolean)(0); // → calling with 0 // → called with 0 - got false 


新しいタむプのプログラムフロヌ制埡を䜜成する関数を䜜成するこずもできたす。

 function unless(test, then) { if (!test) then(); } function repeat(times, body) { for (var i = 0; i < times; i++) body(i); } repeat(3, function(n) { unless(n % 2, function() { console.log(n, "is even"); }); }); // → 0 is even // → 2 is even 


このような堎合、第3章で説明したレキシカルスコヌプルヌルが圹立ちたす。 最埌の䟋では、倉数nは倖郚関数ぞの匕数です。 内偎の関数は倖偎に囲たれおいるため、nを䜿甚できたす。 このような内郚関数の本䜓は、それらを取り巻く倉数にアクセスできたす。 これらは、通垞のルヌプおよび条件匏で䜿甚されるブロック{}の圹割を果たすこずができたす。 重芁な違いは、内郚関数内で宣蚀された倉数が倖郚環境に分類されないこずです。 通垞、これは最高の堎合のみです。

匕数を枡す


前に宣蚀した、別の関数に匕数を枡すノむズの倚い関数は、完党に䟿利ではありたせん。

 function noisy(f) { return function(arg) { console.log("calling with", arg); var val = f(arg); console.log("called with", arg, "- got", val); return val; }; } 


fが耇数のパラメヌタヌを取る堎合、最初のパラメヌタヌのみを受け取りたす。 内郚関数arg1、arg2などに倚数の匕数を远加しお、それらすべおをfに枡すこずは可胜ですが、どれだけの量で十分かはわかりたせん。 さらに、関数fはarguments.lengthで正しく動䜜できたせんでした。 垞に同じ数の匕数を枡すため、最初にいく぀の匕数が䞎えられたかはわかりたせん。

このような堎合、JavaScriptの関数にはapplyメ゜ッドがありたす。 匕数の配列たたは配列の圢匏のオブゞェクトが圌に枡され、圌はこれらの匕数で関数を呌び出したす。

 function transparentWrapping(f) { return function() { return f.apply(null, arguments); }; } 


この関数は圹に立たないが、興味のあるテンプレヌトを瀺しおいる-それによっお返される関数は、受け取ったすべおの匕数をfに枡すが、それ以䞊は䜕もしない。 これは、匕数オブゞェクトに栌玍されおいる独自の匕数をapplyメ゜ッドに枡すこずで発生したす。 applyメ゜ッドの最初の匕数この堎合はnullに蚭定は、メ゜ッド呌び出しを゚ミュレヌトするために䜿甚できたす。 次の章でこの問題に戻りたす。

ゞョン゜ン


JavaScriptには、䜕らかの方法で配列芁玠に関数を適甚する高次関数が広く普及しおいたす。 forEachメ゜ッドは、これらの関数の䞭で最も原始的なものの1぀です。 配列メ゜ッドずしお、関数の他の倚くのオプションにアクセスできたす。 それらを知るために、別のデヌタセットで遊んでみたしょう。

数幎前、誰かが倚くのアヌカむブを調べお、私の姓の歎史に関する本党䜓を䜜成したした。 階士、海賊、錬金術垫を芋぀けるこずを期埅しお、私はそれを開けたした...しかし、それは䞻にフランドルの蟲民で満たされおいたこずが刀明したした。 嚯楜のために、私は盎接の先祖に関する情報を抜出し、コンピュヌタヌで読むのに適した圢匏で蚭蚈したした。

ファむルは次のようになりたす。

 [ {"name": "Emma de Milliano", "sex": "f", "born": 1876, "died": 1956, "father": "Petrus de Milliano", "mother": "Sophia van Damme"}, {"name": "Carolus Haverbeke", "sex": "m", "born": 1832, "died": 1905, "father": "Carel Haverbeke", "mother": "Maria van Brussel"}, 
    ] 


この圢匏はJSONず呌ばれ、JavaScript Object Notationを意味したす。 デヌタストレヌゞおよびネットワヌク通信で広く䜿甚されおいたす。

JSONは、配列ずオブゞェクトの蚘述方法がJavaScriptに䌌おいたすが、いく぀かの制限がありたす。 すべおのプロパティ名は二重匕甚笊で囲む必芁があり、単玔な倀のみが蚱可されたす。関数呌び出し、倉数、蚈算を含たないものは蚱可されたせん。 コメントも蚱可されおいたせん。

JavaScriptは、デヌタをこの圢匏からこの圢匏に倉換するJSON.stringifyおよびJSON.parse関数を提䟛したす。 最初は倀を受け取り、JSONで文字列を返したす。 2番目はそのような行を取り、倀を返したす。

 var string = JSON.stringify({name: "X", born: 1980}); console.log(string); // → {"name":"X","born":1980} console.log(JSON.parse(string).born); // → 1980 


ANCESTRY_FILE倉数はここから入手できたす 。 JSONファむルが文字列ずしお含たれおいたす。 それをデコヌドしお、蚀及された人の数を数えたしょう。

 var ancestry = JSON.parse(ANCESTRY_FILE); console.log(ancestry.length); // → 39 


配列をフィルタヌ凊理する


1924幎に若い人を芋぀けるには、次の機胜が圹立ちたす。 テストに倱敗した配列の芁玠を陀倖したす。

 function filter(array, test) { var passed = []; for (var i = 0; i < array.length; i++) { if (test(array[i])) passed.push(array[i]); } return passed; } console.log(filter(ancestry, function(person) { return person.born > 1900 && person.born < 1925; })); // → [{name: "Philibert Haverbeke", 
}, 
] 


testずいう匕数が䜿甚されたす-これは怜蚌蚈算を実行する関数です。 各芁玠に察しお呌び出され、それによっお返される倀は、この芁玠が返された配列に入るかどうかを決定したす。

ファむルには、1924幎に若い祖父、祖母、いずこの3人がいたした。

フィルタヌ関数は、既存の配列から芁玠を削陀するのではなく、怜蚌された芁玠のみを含む新しい芁玠を䜜成するこずに泚意しおください。 これは、枡された配列を損なわないため、玔粋な関数です。

forEachず同様に、フィルタヌは暙準の配列メ゜ッドの1぀です。 この䟋では、内郚で䜕を行うかを瀺すためだけに、このような関数を説明したした。 これからは、単玔に䜿甚したす。

 onsole.log(ancestry.filter(function(person) { return person.father == "Carel Haverbeke"; })); // → [{name: "Carolus Haverbeke", 
}] 


マップを䜿甚した倉換


祖先の配列をフィルタリングするこずによっお取埗された、人々を衚すオブゞェクトのアヌカむブがあるずしたす。 しかし、読みやすい名前の配列が必芁です。

mapメ゜ッドは、すべおの芁玠に関数を適甚し、返された倀から新しい配列を䜜成するこずにより、配列を倉換したす。 新しい配列の長さは入力ず同じですが、その内容は新しい圢匏に倉換されたす。

 function map(array, transform) { var mapped = []; for (var i = 0; i < array.length; i++) mapped.push(transform(array[i])); return mapped; } var overNinety = ancestry.filter(function(person) { return person.died - person.born > 90; }); console.log(map(overNinety, function(person) { return person.name; })); // → ["Clara Aernoudts", "Emile Haverbeke", // "Maria Haverbeke"] 


興味深いこずに、少なくずも90歳以䞊の人は、1920幎代の若い人たちず同じです。 これは私の蚘録の最新䞖代です。 どうやら、薬は真剣に改善されたした。

forEachやフィルタヌず同様に、mapも配列の暙準的な方法です。

reduceを䜿甚した合蚈


配列を扱うもう1぀の䞀般的な䟋は、配列内のデヌタに基づいお単䞀の倀を取埗するこずです。 1぀の䟋は、すでによく知られおいる数字のリストの合蚈です。 もう1぀は、誰よりも先に生たれた人を怜玢するこずです。

このタむプの高次の操䜜は、reducereductionたたは、fold、foldingず呌ばれたす。 䞀床に1぀の芁玠の配列を折り畳むように想像できたす。 数倀を合蚈するずき、れロから開始し、各芁玠に぀いお、加算を䜿甚しお珟圚の合蚈ず結合したした。

reduce関数のパラメヌタヌは、配列に加えお、結合関数ず初期倀です。 この関数は、フィルタヌやマップよりも明確性が䜎いため、现心の泚意を払っおください。

 function reduce(array, combine, start) { var current = start; for (var i = 0; i < array.length; i++) current = combine(current, array[i]); return current; } console.log(reduce([1, 2, 3, 4], function(a, b) { return a + b; }, 0)); // → 10 


暙準の配列の削枛方法は、もちろん同じように機胜したすが、さらに䟿利です。 配列に少なくずも1぀の芁玠が含たれる堎合、start匕数を省略できたす。 このメ゜ッドは、配列の最初の芁玠を開始倀ずしお受け取り、2番目から䜜業を開始したす。

reduceで知られる最叀の祖先を芋぀けるために、次のように曞くこずができたす

 console.log(ancestry.reduce(function(min, cur) { if (cur.born < min.born) return cur; else return min; })); // → {name: "Pauwels van Haverbeke", born: 1535, 
} 


コンポヌザビリティ


高階関数を䜿甚せずに、先の䟋生幎月日が最も早い人を怜玢するをどのように蚘述できたすか 実際、コヌドはそれほどひどいものではありたせん。

 var min = ancestry[0]; for (var i = 1; i < ancestry.length; i++) { var cur = ancestry[i]; if (cur.born < min.born) min = cur; } console.log(min); // → {name: "Pauwels van Haverbeke", born: 1535, 
} 


倉数が少し倚く、2行長くなりたすが、これたでのずころ、コヌドはかなり明確です。

関数を組み合わせる必芁がある堎合、高階関数は本圓に開きたす。 たずえば、セット内の男性ず女性の平均幎霢を芋぀けるコヌドを蚘述したす。

 function average(array) { function plus(a, b) { return a + b; } return array.reduce(plus) / array.length; } function age(p) { return p.died - p.born; } function male(p) { return p.sex == "m"; } function female(p) { return p.sex == "f"; } console.log(average(ancestry.filter(male).map(age))); // → 61.67 console.log(average(ancestry.filter(female).map(age))); // → 54.56 


加算をプラス関数ずしお定矩する必芁があるのはばかげおいたすが、JavaScriptの挔算子は倀ではないため、匕数ずしお枡すこずはありたせん。

アルゎリズムを倧芏暡なサむクルに埋め蟌む代わりに、性別の決定、幎霢のカりント、数倀の平均化など、関心のある抂念に埓っおすべおが配垃されたす。 それらを順番に適甚しお結果を取埗したす。

わかりやすいコヌドの堎合、これは玠晎らしい機䌚です。 もちろん、明快さは無料ではありたせん。

䟡栌


゚レガントなコヌドず矎しい虹の幞せな土地に、Inefficiencyずいう名前の掟手なモンスタヌがいたす。

配列を凊理するプログラムは、明確に分離された䞀連のステップずしお最も矎しく衚珟されたす。各ステップは、配列で䜕かを実行し、新しい配列を返したす。 しかし、これらすべおの䞭間配列を階局化するこずは高䟡です。

同様に、関数をforEachに枡しお配列を通過させるのは䟿利で理解しやすいです。 ただし、JavaScriptで関数を呌び出すこずは、ルヌプよりも高䟡です。

これは、プログラムの読みやすさを向䞊させる倚くの手法にも圓おはたりたす。 抜象化は、コンピュヌタヌのクリヌンな䜜業ず䜜業する抂念の間にレむダヌを远加したす。その結果、コンピュヌタヌはより倚くの䜜業を行いたす。 これは厳密なルヌルではありたせん-効率を犠牲にするこずなく抜象化を远加できる蚀語があり、JavaScriptでさえ、経隓豊富なプログラマヌが抜象的で高速なコヌドを曞く方法を芋぀けるこずができたす。 しかし、この問題は䞀般的です。

幞いなこずに、ほずんどのコンピュヌタヌはめちゃくちゃ速いです。 デヌタセットが倧きすぎない堎合、たたは実行時間を人の芳点から芋お十分に高速にする必芁がある堎合たずえば、ナヌザヌがボタンを抌すたびに䜕かを実行するため-動䜜する矎しい゜リュヌションを䜜成しおもかたいたせん0.5ミリ秒、たたは非垞に最適化されおおり、1/10ミリ秒で機胜したす。

このコヌドが呌び出される頻床を倧たかに蚈算するず䟿利です。 ルヌプ内にルヌプがある堎合盎接、たたは内郚でルヌプずも機胜する関数のルヌプ内の呌び出しを介しお、コヌドはN * M回実行されたす。ここで、Nは倖偎のルヌプの繰り返し数、Mは内偎のルヌプの繰り返し数です。 内偎のルヌプにP回繰り返される別のサむクルがある堎合、すでにN * M * P-を取埗したす。 これは倧きな数に぀ながる可胜性があり、プログラムの速床が䜎䞋するず、倚くの堎合、問題は最も内偎のルヌプ内の小さなコヌドに瞮小されたす。

グレヌトグレヌトグレヌトグレヌトグレヌト...


私の祖父、フィリバヌトハヌバヌベケは、デヌタファむルに蚘茉されおいたす。 圌から始めお、私の祖先である最幎長のパり゚ル・ファン・ハベルベック、私の盎接の祖先を探しお家族を远跡できたす。 今、私は圌からのDNAの割合を蚈算したい理論䞊。

祖先の名前からそれを衚すオブゞェクトに移動するには、名前ず人に䞀臎するオブゞェクトを䜜成したす。

 var byName = {}; ancestry.forEach(function(person) { byName[person.name] = person; }); console.log(byName["Philibert Haverbeke"]); // → {name: "Philibert Haverbeke", 
} 


タスクは、各レコヌドで父芪を芋぀けお、パり゚ルたでの歩数を蚈算するだけではありたせん。 家族の歎史では、いずこの間でいく぀かの結婚がありたした井戞、小さな村など。 この点で、ある堎所の家系図の枝は他の堎所ず぀ながっおいるので、1/2 GGはパり゚ルず私の間の䞖代数よりも倚くの遺䌝子を取埗したす。 この匏は、各䞖代が遺䌝基金を2぀に分割するずいう仮定に基づいおいたす。

デヌタを巊から右に順番に結合するこずで配列が単䞀の倀に削枛される堎合、reduceを䜿甚しお類掚するのが合理的です。 ここでも特異点を取埗する必芁がありたすが、遺䌝の線に埓う必芁がありたす。 そしお、それらは単玔なリストではなく、ツリヌを圢成したす。

特定の人の祖先のこれらの倀を組み合わせお、この倀を考慮したす。 これは再垰的に実行できたす。 ある皮の人が必芁な堎合は、䞡芪に必芁な倀を蚈算する必芁があり、そのために祖先などの蚈算が必芁になりたす。 , , - . , . – , , .

, , reduceAncestors «» .

 function reduceAncestors(person, f, defaultValue) { function valueFor(person) { if (person == null) return defaultValue; else return f(person, valueFor(byName[person.mother]), valueFor(byName[person.father])); } return valueFor(person); } 


valueFor . . person f, .

, , .

 function sharedDNA(person, fromMother, fromFather) { if (person.name == "Pauwels van Haverbeke") return 1; else return (fromMother + fromFather) / 2; } var ph = byName["Philibert Haverbeke"]; console.log(reduceAncestors(ph, sharedDNA, 0) / 4); // → 0.00049 


, , 100% ( ), 1. .

0.05% 16 . , , . , 3 , - .

reduceAncestors. ( ) ( ) . , , 70 .

 function countAncestors(person, test) { function combine(person, fromMother, fromFather) { var thisOneCounts = test(person); return fromMother + fromFather + (thisOneCounts ? 1 : 0); } return reduceAncestors(person, combine, 0); } function longLivingPercentage(person) { var all = countAncestors(person, function(person) { return true; }); var longLiving = countAncestors(person, function(person) { return (person.died - person.born) >= 70; }); return longLiving / all; } console.log(longLivingPercentage(byName["Emile Haverbeke"])); // → 0.145 


, . , reduceAncestors – .


bind, , , , .

, . isInSet, , . filter , isInSet, , isInSet .

 var theSet = ["Carel Haverbeke", "Maria van Brussel", "Donald Duck"]; function isInSet(set, person) { return set.indexOf(person.name) > -1; } console.log(ancestry.filter(function(person) { return isInSet(theSet, person); })); // → [{name: "Maria van Brussel", 
}, // {name: "Carel Haverbeke", 
}] console.log(ancestry.filter(isInSet.bind(null, theSet))); // → 
 same result 


bind , isInSet theSet, , bind.

, null, – , apply. .

たずめ


– , JavaScript. « » , , .

– forEach, - , filter – , , map – , , reduce – .

apply, . bind .



reduce concat , .

 var arrays = [[1, 2, 3], [4, 5], [6]]; //    // → [1, 2, 3, 4, 5, 6] 



, ( ). average, .

– , , . byName, .

 function average(array) { function plus(a, b) { return a + b; } return array.reduce(plus) / array.length; } var byName = {}; ancestry.forEach(function(person) { byName[person.name] = person; }); //    // → 31.2 



, 90 . . . , , 100 : Math.ceil(person.died / 100).

 function average(array) { function plus(a, b) { return a + b; } return array.reduce(plus) / array.length; } //    // → 16: 43.5 // 17: 51.2 // 18: 52.8 // 19: 54.8 // 20: 84.7 // 21: 94 


groupBy, . , , , .

Every some

every some. , , , true false. , && true, true, every true, true . , some true, true . , – , some true , .

every some, , , .

 //    console.log(every([NaN, NaN, NaN], isNaN)); // → true console.log(every([NaN, NaN, 4], isNaN)); // → false console.log(some([NaN, 3, 4], isNaN)); // → true console.log(some([2, 3, 4], isNaN)); // → false 

Source: https://habr.com/ru/post/J241155/


All Articles