Help us understand the problem. What is going on with this article?

Array.prototype.reduce の第二引数で sum 値を初期化しましょうという話

More than 3 years have passed since last update.
[1,2,3].reduce(function(a,b){return a + b});// 6

sum(配列の合計を求め)るとき、reduceを使うと便利ですが、いくつか注意すべき点があります。

.length0 で失敗

空の配列に.reduceを使用すると、例外を起こします。

[].reduce(function(a,b){return a + b});
// Uncaught TypeError: Reduce of empty array with no initial value

これは、第二引数0 を与えれば解決します。

[].reduce(function(a,b){return a + b},0);// 0

.length が 1 で成功、だが…

数値であれば意図通りです。

[1].reduce(function(a,b){return a + b},0);// 1

コレクションの場合、失敗します。

[{value:1}].reduce(function(a,b){return (a.value!=null? a.value: a) + b.value});
// {value: 1}

MDNにはこうあります。

var result = array.reduce(callback[, initialValue]);
callback
4 つの引数を取って、配列内の各値に対し実行するコールバック関数
previousValue
現在処理されている配列要素の 1 つ前の要素。もしくは、initialValueinitialValue > については、後で述べます。
currentValue
現在処理されている配列要素
index
現在処理されている配列要素のインデックス
array
reduce に呼ばれた配列
initialValue
callback の最初の呼び出しのときに、最初の実引数として用いるためのオブジェクト。
関数が呼び出される初回は、 previousValuecurrentValue は 2 つの値のうちの 1 つを取り得ます。reduce 呼び出し時に、initialValue が与えられた場合、previousValueinitialValue と等しくなり、currentValue は、配列の最初の値と等しくなります。 initialValue が与えられなかった場合、previousValue は配列の最初の値と等しくなり、currentValue は、2 番目の値と等しくなります。
Array.prototype.reduce() - JavaScript | MDN

やはり、第二引数を与えましょう。

[{value:1}].reduce(function(a,b){return (a.value!=null? a.value: a) + b.value},0);
// 1

callbackの引数 a は数値で安定するため、 a.value をチェックする必要がなくなりました。

[{value:1}].reduce(function(a,b){return a + b.value},0);
// 1

Promiseと組み合わせて非同期の直列処理を使う

async.waterfall のように、非同期処理を1つずつ実行したいときに、ES6 Promisesと組み合わせて、下記のように書けます。

// a、bの位置に注意
[1,2,3].reduce(function(promise,b){
  return promise.then(function(a){
    return new Promise(function(resolve){
      console.log('Start task '+b);

      setTimeout(function(){
        console.log('End task '+b);
        resolve(a + b)
      },500);
    });
  });
},Promise.resolve(0))
.then(function(total){
  console.log(total);// 6
});

resolve で次のタスクに値を渡します。setTimeoutを、XMLHttpRequest / fetch1、他の非同期処理などに書き換えれば、スクレイピングや、jsonの集計などに応用できます。

参考: コレクションのバカ騒ぎ | Promiseアンチパターン - くじら公園

まとめ

初期化しようぜ


  1. まともなコード載ってるページが英語しか見つけられなかった 

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away