経緯
「JavaScriptのMathオブジェクトのsumメソッドについて現役エンジニアが解説」というタイトルの記事が出てきて、最近だと Math.sum() 実装されてるんか。へー。って思って読んだら「Math.sum() はないので自分で実装しましょう」という内容でプログラミングスクール滅べと思った。
これ、検索して読みましたが、任意個数の引数を合計するメソッドと思いきや、単にa+bを返すメソッドだったので、「恥を知れ」と思いました
JavaScript、Array.prototype.reduceがあるから、
nums.reduce((x, y) => x + y)でええんちゃうの…?
元ネタと思われるコード
多分、これ。
JavaScriptのMathオブジェクトのsumメソッドについて現役エンジニアが解説【初心者向け】
var sum = function (a, b) {
return a + b;
};
console.log(sum(1, 2));現役ハッカー(略)が解説
そのコードは
1 + 2と等価なので、完全にフールである。
JavaScriptにはMath.sum()は存在しない。
だが、そもそもそのようなものは必要ないし、そもそもsum関数があるとして、一般的にはイテレータ操作だから、MathよりはArrayやEnumeratorに属するべきものだ。
私が言及した
nums.reduce((x, y) => x + y)は有効なコードであであり、関数の自作などせずとも目的を達成できる。
Array.prototype.reduce()はRubyで言うところのEnumberable#injectのようなものである。
コールバック関数を受け取り、Array.prototype.forEachのようなイテレータ操作メソッドが追加された過程で追加されたものである。
Mozilla Firefox 3からサポートされた。
コールバック関数は2つの引数を取り、(最後の戻り値, 次の値)である。
[1, 2, 3].reduce()だとしたら、まずひとつ目の値である1はコールバックの評価をされず戻り値という扱いになる。
そして、1回目のコールバック関数は(1, 2)という引数で起動される。
2回目のコールバック関数のひとつ目の引数は、この1回目のコールバック関数の戻り値となり、2つ目の引数は3となる。
() =>という書き方は、最近の関数の書き方だ。
まず、(arg) => {code}というアロー関数という形式がある。
引数がひとつである場合、カッコは省略でき、arg => {code}と書くことができる。
さらに新しい書き方としてcodeを囲むブレースを省略できる。
これは単一の式文からなる場合に省略でき、省略した場合returnが自動的に行われる。
そのため、
(x, y) => x + yは
(x, y) => { return x + y }と等価である。
これらを組み合わせて、
nums.reduce((x, y) => x + y)が適切な答えとなる。
なお、この形式のアロー関数がサポートされたのはかなり最近(Firefox 52/Chrome 58)なので、ブラウザ互換性を重視するならば、
nums.reduce(function(x, y) { return x + y})となる。