Esta tradução está incompleta. Por favor, ajude a traduzir este artigo.

Resumo

O método reduce() utiliza uma função sobre um acumulador (seria quase um sinônimo para array com elementos numéricos) e cada elemento do array (da esquerda para direita), reduzindo-a a um único valor.

Sintaxe

array.reduce(callback[, valorInicial])

Parâmetros

callback
Função que é executada em cada valor no array, recebe quatro argumentos:

Acumulador
O valor retornado na última invocação do callback, ou o argumento Valor Inicial, se fornecido. (exemplo abaixo).
valorAtual
O elemento atual que está sendo processado no array.
indice
O índice do elemento atual que está sendo processado no array.
array
O array ao qual a função reduce() foi chamada.
valorInicial
Opcional. Objeto a ser usado como o primeiro argumento da primeira chamada da função callback. Chamar reduce() em uma array vazia sem valor inicial é um erro.

 

Valor de retorno

O valor que resulta da redução.

 

Descrição

O reduce()  executa a função de callback uma vez para cada elemento presente no array, excluindo furos (valores indefinidos) , recebendo quatro argumentos:

  • o valor inicial (ou o valor do callback anterior),
  • o valor do elemento corrente,
  • o índice corrente e
  • o array onde a iteração está ocorrendo.

A primeira vez que o callback é chamado, o Acumulador e o valorAtual podem ter um de dois valores possíveisSe o Valor Inicial tiver sido fornecido na chamada à função reduce(), então o Acumulador será igual ao valorInicial e o valorAtual será igual ao primeiro valor no array.

Nota: Se o valorInicial não tiver sido passado como argumento, então Acumulador será igual ao primeiro valor no array e valorAtual será igual ao segundo.

Se a array estiver vazia e o valorInicial não tiver sido informado, uma exceção do tipo TypeError será lançada. Se a array possuir somente um elemento (independente da posição) e valorInicial não tiver sido fornecido, ou se valorInicial for fornecido, mas a array estiver vazia, o valor será retornado sem que a função de callback seja chamada.

É  mais seguro provir um valor inicial, porque existem tres possíveis saídas sem o valorInicial como mostrado no exemplo:

 

var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );

// reduce() sem valores iniciais
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42
[ { x: 22 }            ].reduce( maxCallback ); // { x: 22 }
[                      ].reduce( maxCallback ); // TypeError

// map/reduce; melhor solução, funciona para vetores vazios e tambem para vetores grandes 
[ { x: 22 }, { x: 42 } ].map( el => el.x )
                        .reduce( maxCallback2, -Infinity );

 

Como funciona o reduce()

Suponha o seguinte uso de reduce tenha ocorrido:

[0, 1, 2, 3, 4].reduce(function(Acumulador, valorAtual, indice, array) {
  return Acumulador + valorAtual;
});
// 10

O callback será invocado quatro vezes com os argumentos e retorna os valores em cada chamada, como sendo:

  Acumulador valorAtual indice array valor de retorno
primeira chamada 0 1 1 [0, 1, 2, 3, 4] 1
segunda chamada 1 2 2 [0, 1, 2, 3, 4] 3
terceira chamada 3 3 3 [0, 1, 2, 3, 4] 6
quarta chamada 6 4 4 [0, 1, 2, 3, 4] 10

O valor retornado pelo reduce será o da última chamada à callback (10).

Você também pode dar uma Arrow Function em vez de uma função completa. O código abaixo produz a mesma saída que o código do bloco acima:

 

[0, 1, 2, 3, 4].reduce( (accum, curr) => accum + curr );

 

Se você informar um valor inicial como o segundo argumento de reduce, o resultado será:

[0, 1, 2, 3, 4].reduce(function(acumulador, valorAtual, indice, array) {
  return acumulador + valorAtual;
}, 10);

// 20
callback Acumulador valorAtual indice array valor de retorno
primeira chamada 10 0 0 [0, 1, 2, 3, 4] 10
segunda chamada 10 1 1 [0, 1, 2, 3, 4] 11
terceira chamada 11 2 2 [0, 1, 2, 3, 4] 13
quarta chamada 13 3 3 [0, 1, 2, 3, 4] 16
quinta chamada 16 4 4 [0, 1, 2, 3, 4] 20

O retorno da última chamada 20,é retornado como resultado da função reduce().

Exemplos

Soma todos os valores de uma array

var total = [0, 1, 2, 3].reduce(function(a, b) {
  return a + b;
});
// total == 6

Redução de um array de arrays

var reduzido = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
  return a.concat(b);
});
// reduzido é [0, 1, 2, 3, 4, 5]

 

Contando valores iguais em um objeto

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];

var countedNames = names.reduce(function (allNames, name) { 
  if (name in allNames) {
    allNames[name]++;
  }
  else {
    allNames[name] = 1;
  }
  return allNames;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

Juntando arrays contidos num array de objetos usando o operador spread e o valorInicial

// friends - um array de objetos 
// onde o campo "books" é a lista de livros favoritos 
var friends = [{
  name: 'Anna',
  books: ['Bible', 'Harry Potter'],
  age: 21
}, {
  name: 'Bob',
  books: ['War and peace', 'Romeo and Juliet'],
  age: 26
}, {
  name: 'Alice',
  books: ['The Lord of the Rings', 'The Shining'],
  age: 18
}];

// allbooks - lista que contém todos os livros de friends +
// lista adicional contida em valorInicial
var allbooks = friends.reduce(function(prev, curr) {
  return [...prev, ...curr.books];
}, ['Alphabet']);

// allbooks = [
//   'Alphabet', 'Bible', 'Harry Potter', 'War and peace', 
//   'Romeo and Juliet', 'The Lord of the Rings',
//   'The Shining'
// ]

 

Removendo itens duplicados num array

let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
let result = arr.sort().reduce((init, current) => {
    if (init.length === 0 || init[init.length - 1] !== current) {
        init.push(current);
    }
    return init;
}, []);
console.log(result); //[1,2,3,4,5]

Rodando promises em sequência

/**
 * Roda promises de um promise array de uma maneira encadeada
 *
 * @param {array} arr - promise arr
 * @return {Object} promise object
 */
function runPromiseInSequense(arr) {
  return arr.reduce((promiseChain, currentPromise) => {
    return promiseChain.then((chainedResult) => {
      return currentPromise(chainedResult)
        .then((res) => res)
    })
  }, Promise.resolve());
}

// promise function 1
function p1() {
  return new Promise((resolve, reject) => {
    resolve(5);
  });
}

// promise function 2
function p2(a) {
  return new Promise((resolve, reject) => {
    resolve(a * 2);
  });
}

// promise function 3
function p3(a) {
  return new Promise((resolve, reject) => {
    resolve(a * 3);
  });
}

const promiseArr = [p1, p2, p3];
runPromiseInSequense(promiseArr)
  .then((res) => {
    console.log(res);   // 30
  });

 

Polyfill

Array.prototype.reduce foi adicionado ao padrão ECMA-262  na quinta edição; e portanto, pode não estar presente em todas as implementações do padrão. Você pode contornar isso inserindo o código a seguir no início de seus scripts, permitindo o uso do reduce() em implementações que não possuem suporte nativo a ele.

// Etapas de produção para o ECMA-262, Edition 5, 15.4.4.21
// Referencia: http://es5.github.io/#x15.4.4.21
if (!Array.prototype.reduce) {
  Array.prototype.reduce = function(callback /*, valorInicial*/) {
    'use strict';
    if (this == null) {
      throw new TypeError('Array.prototype.reduce chamado é nulo (null) ou indefinido (undefined)');
    }
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' não é uma função')
    }
    var t = Object(this), len = t.length >>> 0, k = 0, value;
    if (arguments.length == 2) {
      value = arguments[1];
    } else {
      while (k < len && !(k in t)) {
        k++; 
      }
      if (k >= len) {
        throw new TypeError('Reduce possui um array vazio sem um valor inicial');
      }
      value = t[k++];
    }
    for (; k < len; k++) {
      if (k in t) {
        value = callback(value, t[k], k, t);
      }
    }
    return value;
  };
}

Especificações

Especificação Status Comentário
ECMAScript 5.1 (ECMA-262)
The definition of 'Array.prototype.reduce' in that specification.
Padrão

Definição inicial. Implemetada no JavaScript 1.8.

ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Array.prototype.reduce' in that specification.
Padrão  

Compatibilidade do Browser

Estamos convertendo nossos dados de compatibilidade para o formato JSON. Esta tabela de compatibilidade ainda usa o formato antigo, pois ainda não convertemos os dados que ela contém. Descubra como você pode ajudar!

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari Microsoft Edge
Suporte básico (Yes) 3.0 (1.9) 9 10.5 4.0 (Yes)
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Suporte básico (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)

Leia também

Etiquetas do documento e colaboradores

Última atualização por: geekcom,