Every e some: os métodos de array em Javascript que respondem "sim" ou "não"
Tags: some, every, javascript, githubbrasil
Published: 2023-11-16 02:08:50

## Os métodos de array every e some em Javascript servem para responder perguntas com "sim" ou "não", ou "true" e "false". Clique e confira.
 
**Tudo** ou **pelo menos um**.
 
Essa é a forma mais resumida de explicar o every e some em Javascript:
 
- O método **every** ("todo" ou "toda" em inglês) responde se **todos** os itens de uma array atendem aos requisitos
- Já o **some** ("algum" ou "alguma") diz se **pelo menos algum** item atende aos requisitos
 
Esse tipo de pergunta é respondida com "sim" ou "não". Ou na programação, **true** ou **false**.
 
Por exemplo, todos os itens da array abaixo estão acima de zero?
 
![execução do every em uma array com return false](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1700007173-execucao-do-every-em-uma-array-com-return-false.png%3Fauto%3Dformat&w=3840&q=75)
 
```javascript
const numbers = [ 3, 7, -1, 7, 10 ];

const result = numbers.every(function(number) {
  if (number > 0) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // false
```
 
A resposta é **false**, ou "não", nem todos os números estão abaixo de zero. Se eu removesse o `-1`, a resposta seria diferente.
 
Com o some, a lógica é muito parecida. Porém basta que um item atenda aos requisitos para o retorno ser **true**:
 
![execução do some em uma array com return true](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1700007200-execucao-do-some-em-uma-array-com-return-true.png%3Fauto%3Dformat&w=3840&q=75)
 
```javascript
const numbers = [ 3, 7, -1, 7, 10 ];

const result = numbers.some(function(number) {
  if (number > 0) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // true
```
 
Nesse caso, quatro dos cinco números da array estão acima de zero, então a resposta é "sim, pelo menos um número está acima de zero".
 
Veja agora outros detalhes importantes sobre esses métodos.
 
## Every e some em Javascript
 
Como já falei, esses métodos são muito parecidos.
 
Então de agora em diante, tudo que você ler se aplica a ambos. A única diferença entre eles já expliquei na introdução, e vou mostrar nos desafios também.
 
A estrutura desses métodos é receber uma função callback que executa a cada item da array:
 
```javascript
const numbers = [ 3, 7, -1, 7, 10 ];

numbers.some(function(number) {
  console.log(number);
});

/* 
  3
  7
  -1
  7
  10
*/
```
 
Eles devem "partir" de uma array, já que ela é dona desses métodos:
 
```javascript
const numbers = [ 3, 7, -1, 7, 10 ];

numbers.some();

// Ou

numbers.every();

// Ou

[ 3, 7, -1, 7, 10 ].some();

// Ou

[ 3, 7, -1, 7, 10 ].every();
```
 
Ou seja: algo que represente uma array + o ponto + o nome do método.
 
Apesar de haver uma iteração, o every e o some podem não executar em todos os itens.
 
## Every e some podem parar de executar no meio da array
 
E isso não é por preguiça.
 
Esses métodos não precisam executar em todos os itens da array. Dependendo dos primeiros resultados, a resposta final não mudará.
 
Acompanhe esse raciocínio do every:
 
- Já que o every responde se **todos os itens da array atendem aos requisitos**, se qualquer item não atender, a resposta final já será `false`. Mesmo que todos os outros sejam `true`.
 
![every em javascript parando no meio da execução](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1700007232-every-em-javascript-parando-no-meio-da-execucao.png%3Fauto%3Dformat&w=3840&q=75)
 
```javascript
const numbers = [ 2, -3, 4, 5, 6 ];

const result = numbers.every(function(number) {
  console.log('O número atual é: ', number);
  if (number > 0) {
    return true;
  } else {
    return false;
  }
});

console.log('O resultado é: ', result);
```
 
Esse código mostra no console o número atual a cada iteração. E no final exibe o resultado:
 
```
O número atual é: 2
O número atual é: -3
O resultado é: false
```
 
Na primeira iteração, `number` é 2, e tudo bem, já que ele está acima de zero. Porém na segunda iteração (-3), o próximo console já é o resultado final, ou seja, ele não iterou pelos números 4, 5 e 6.
 
Isso acontece porque, mesmo que todos os outros itens retornem `true`, já se sabe que **nem todos** os itens atendem aos requisitos.
 
Isso acontece porque, mesmo que os próximos itens retornem `true`, **nem todos** atendem aos requisitos.
 
---
 
Com o some acontece a mesma coisa:
 
- Já que ele verifica se **pelo menos um item da array atende aos requisitos**, caso ele encontre um que não atende, não tem porquê continuar a execução.
 
![some em javascript parando no meio da execução](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1700007254-some-em-javascript-parando-no-meio-da-execucao.png%3Fauto%3Dformat&w=3840&q=75)
 
A array de exemplo abaixo é um pouco diferente mas a lógica do teste com os consoles é a mesma:
 
```javascript
const numbers = [ 2, 3, 4, -5, 6 ];

const result = numbers.some(function(number) {
  console.log('O número atual é: ', number);
  if (number < 0) {
    return true;
  } else {
    return false;
  }
});

console.log('O resultado é: ', result);
```
 
O resultado final será:
 
```
O número atual é: 2
O número atual é: 3
O número atual é: 4
O número atual é: -5
O resultado é: true
```
 
Quando o some encontra o primeiro número abaixo de zero (o critério), ele finaliza, já que **pelo menos um** item atende aos requisitos. É por isso que após o console do -5, vem o resultado, porque o some não iterou no último número, o 6.
 
---
 
Acho que já ficou claro para você, mas o retorno da função callback de every e some é bem importante.
 
## O retorno da função callback de every e some
 
O retorno sempre é um booleano.
 
Isso acontece porque e cada iteração, é preciso dizer se o item atende ou não aos requisitos. E isso sempre acontece com um `true` ou `false`.
 
E se eu retornar algo que não é um booleano?
 
```javascript
const numbers = [ -1, 0, 1 ];

const result = numbers.every(function(number) {
  return number;
});

console.log(result); // false
```
 
Eu retornei o próprio `number`, e o resultado final foi `false`. Por quê?!
 
Quando o retorno não é um booleano explícito, o Javascript converte para poder prosseguir. Essa conversão se chama **coerção de tipos**.
 
Veja o que acontece com cada conversão:
 
```javascript
const numbers = [ -1, 0, 1 ];

const result = numbers.every(function(number) {
  console.log(number + ' é ' + Boolean(number));
  return number;
});

console.log('O resultado é: ', result);
```
 
Adicionei um novo console dentro da função callback para mostrar como fica cada número após a conversão. E olha no que deu:
 
```
-1 é true
0 é false
O resultado é: false
```
 
**O ponto principal é: qualquer número que não seja zero, quando você converte para booleano, vira `true`. Assim que o every encontrou o zero, ele retornou `false` e parou a execução.**
 
O mesmo acontece com o some:
 
```javascript
const numbers = [ -1, 0, 1 ];

const result = numbers.some(function(number) {
  console.log(number + ' é ' + Boolean(number));
  return number;
});

console.log('O resultado é: ', result);

/*
  -1 é true
  O resultado é: true
*/
```
 
Quando o some encontra o `-1`, que é `true` após a conversão, ele já finaliza.
 
Então nunca esqueça: o retorno da função callback de every e some sempre é um booleano.
 
Em todos os exemplos que dei, a função callback recebeu apenas o número como parâmetro. Mas é possível deixar a brincadeira mais interessante.
 
## Os parâmetros da função callback de every e some
 
A função callback pode receber até 3 parâmetros:
 
1. Item
2. Index
3. Array
 
A partir de agora vou explicar cada um e propor um desafio para fixar bem o conteúdo.
 
Para isso, vou usar a array abaixo como base para os desafios (a área está em mil km²):
 
```javascript
const maioresCidadesBrasil = [
  { nome: 'São Paulo',      estado: 'SP', area: 1521,  fusoHorario: 'UTC-3', clubesFutebol: [ 'Corinthians', 'Palmeiras', 'São Paulo', 'Santos' ] },
  { nome: 'Rio de Janeiro', estado: 'RJ', area: 1200,  fusoHorario: 'UTC-3', clubesFutebol: [ 'Flamengo', 'Fluminense', 'Vasco', 'Botafogo' ]     },
  { nome: 'Brasília',       estado: 'DF', area: 5800,  fusoHorario: 'UTC-3', clubesFutebol: [ 'Brasiliense', 'Gama' ]                             },
  { nome: 'Salvador',       estado: 'BA', area: 706,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Bahia', 'Vitória' ]                                },
  { nome: 'Fortaleza',      estado: 'CE', area: 314,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Ceará', 'Fortaleza' ]                              },
  { nome: 'Belo Horizonte', estado: 'MG', area: 331,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Atlético Mineiro', 'Cruzeiro' ]                    },
  { nome: 'Manaus',         estado: 'AM', area: 11400, fusoHorario: 'UTC-4', clubesFutebol: [ 'Fast Clube' ]                                      },
  { nome: 'Curitiba',       estado: 'PR', area: 435,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Atlético Paranaense', 'Coritiba' ]                 },
  { nome: 'Recife',         estado: 'PE', area: 218,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Náutico', 'Sport' ]                                },
  { nome: 'Porto Alegre',   estado: 'RS', area: 496,   fusoHorario: 'UTC-3', clubesFutebol: [ 'Grêmio', 'Internacional' ]                         }
];
```
 
Veja agora cada um dos parâmetros.
 
### Primeiro parâmetro: item
 
O primeiro parâmetro você já conhece.
 
É o único obrigatório e usei ele em todos os exemplos até agora. Então resolva esse desafio: *todas as 10 maiores cidades do Brasil têm uma área acima de 300 mil km²?*
 
Aqui, basta verificar a propriedade `.area`:
 
```javascript
const result = maioresCidadesBrasil.every(function(cidade) {
  if (cidade.area > 300) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // false
```
 
O resultado é `false`, porque **nem todas as cidades** possuem área acima de 300 mil km². Recife quebra esse padrão por ter apenas 218 mil km². Agora, se eu alterar o critério para 200 mil Km², o resultado muda:
 
```javascript
const result = maioresCidadesBrasil.every(function(cidade) {
  if (cidade.area > 200) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // true
```
 
---
 
Agora um desafio para resolver com o some: *entre as 10 maiores cidades do Brasil, existe alguma da Bahia (BA)?*
 
O interessante desse tipo de teste é que você pode bater o olho na array e descobrir a resposta final. E depois que aplicar o código, fará a prova real (até rimou). Acredito que é muito produtivo aprender assim:
 
```javascript
const result = maioresCidadesBrasil.some(function(cidade) {
  if (cidade.estado === 'BA') {
    return true;
  } else {
    return false;
  }
});

console.log(result); // true
```
 
Aqui apenas verifico se a propriedade `.estado` das cidades é igual ao estado da Bahia. Como existe **pelo menos um item na array que atende ao requisito**, o resultado final é `true`.
 
Os desafios foram fáceis? Legal, veja agora o próximo parâmetro.
 
### Segundo parâmetro: index
 
Ele é um número.
 
Na primeira iteração seu valor é zero, e a partir das próximas aumenta de 1 em 1.
 
```javascript
maioresCidadesBrasil.some(function(cidade, index) {
  console.log(index);
});

/*
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
*/
```
 
O último index é sempre igual à quantidade de itens da array menos 1. É por isso que o último index da array de cidades é 9, pois tem 10 itens.
 
Esse número é muito útil para várias situações, como por exemplo resolver o próximo desafio: *verifique se todas as cidades estão no fuso horário `UTC-3`, com exceção do item na posição 6*.
 
Quero deixar claro que esse desafio serve apenas para você entender o parâmetro `index`. Dificilmente você encontrará isso em um projeto real.
 
Para começar o código, vou criar um `if` que ignora o item 6 (cidade de Manaus, a única com fuso horário UTC-4). Quando ele vier, retorno `true` para que ele não altere o resultado final:
 
```javascript
const result = maioresCidadesBrasil.every(function(cidade, index) {
  if (index === 6) {
    return true;
  }
});
```
 
O código ainda não está pronto, pois preciso lidar com todos os outros itens da array. E para isso vou adicionar um outro `if` que verifica o fuso horário deles. Se for "UTC-3", retorno `true` também. Por fim, deixo um `return false` para todos os outros casos:
 
```javascript
const result = maioresCidadesBrasil.every(function(cidade, index) {
  if (index === 6) {
    return true;
  }
  
  if (cidade.fusoHorario === 'UTC-3') {
    return true;
  }
  
  return false;
});

console.log(result); // true
```
 
O resultado final é `true`, já que, com exceção de Manaus, todas as outras cidades estão no fuso horário UTC-3. Se você fizer o teste de remover o primeiro `if`, verá que o resultado final muda para `false`.
 
---
 
Agora um desafio com o some: *descubra se a array tem pelo menos uma cidade que tem apenas um clube de futebol na propriedade `clubesFutebol`, com exceção do index 6.*
 
O código começa bem parecido com o anterior:
 
```javascript
maioresCidadesBrasil.some(function(cidade, index) {
  if (index === 6) {
    return false;
  }
});
```
 
Eu verifico se o index é 6, e nesse caso retorno `false` e não `true`. Isso porque, caso eu retornasse `true`, eu não responderia à pergunta do desafio e sim outra pergunta. Que seria *a array de cidade tem algum item no índice 6?* ou *a array de cidades tem pelo menos 7 itens?*. E é mais simples responder essas perguntas de outras formas.
 
Se o index não for 6, então adiciono outro `if` para verificar quantos times tem a array `clubesFutebol`. Se for 1, retorno `true` significa que achei minha resposta e o some finaliza a execução. Ao final deixo um `return false` para deixar claro que acontece, mas ele é opcional:
 
```javascript
const result = maioresCidadesBrasil.some(function(cidade, index) {
  if (index === 6) {
    return false;
  }
  
 if (cidade.clubesFutebol.length === 1) {
   return true;
 }
  
  return false;
});

console.log(result); // false
```
 
A resposta final é `false`, porque, com exceção do item no índice 6, todos os outros tem mais de 1 clube na array `clubesFutebol`. Assim como no exemplo anterior, se você remover o primeiro `if`, verá que o resultado muda para `true`. Justamente pela cidade de Manaus que tem apenas o Fast Clube na array.
 
---
 
O index também é importante para outras operações, como descobrir se o item está em uma posição par ou impar na array. Expliquei isso nesse post sobre o [método map em Javascript](https://demenezes.dev/posts/map-javascript-array/#o-segundo-par%C3%A2metro-do-map--index).
 
Veja agora o último parâmetro da função callback.
 
### Terceiro parâmetro: array
 
Esse é o único parâmetro que não muda.
 
Ao longo das iterações, seu valor sempre é a array que você está iterando:
 
```javascript
maioresCidadesBrasil.some(function(cidade, index, array) {
  console.log(array) // maioresCidadesBrasil: [ ... ]
});
```
 
O código acima escreve no console a array `maioresCidadesBrasil` a cada iteração. É importante você usar esse parâmetro apenas como consulta para outras operações, e nunca para mudar a array.
 
Esse último desafio farei apenas com o some: *a array possui duas cidades no mesmo estado*?
 
Por favor, muita atenção, isso aqui é muito importante. Num primeiro momento, parece que o some não pode resolver o desafio. Mas é seu trabalho como pessoa programadora transpor o problema de negócio (nesse caso, o desafio) para o código.
 
Então você pode ler a frase do desafio de outra forma: *existe pelo menos uma cidade que tenha o valor da propriedade `estado` igual a de outra cidade?*
 
Agora que eu coloquei o trecho **pelo menos** no meio do desafio, ficou mais claro?
 
Começo o código com a variável `quantidade`. Ela irá contar quantas cidades fazem parte do mesmo estado da cidade da iteração atual. E isso acontece a cada iteração:
 
```javascript
maioresCidadesBrasil.some(function(cidade, index, array) {
  let quantidade = 0;
});
```
 
Criei a variável `quantidade` que vai contar isso para mim. Agora, dentro da função callback vou fazer um `for` no parâmetro `array`. Dentro do `for`, se o estado for igual ao estado da cidade que estou iterando no every, adiciono 1 a essa variável:
 
```javascript
maioresCidadesBrasil.some(function(cidade, index, array) {
  let quantidade = 0;
  
  for (i = 0; i < array.length; i++) {
    if (array[i].estado === cidade.estado) {
      quantidade = quantidade + 1;
    }
  }
  
  console.log(quantidade); // 1
  
  return true;
});
```
 
No final, eu coloquei um console na variável e um `return true`, que serve apenas para o every iterar até o final. O console sempre vai me mostrar o valor 1, ou seja, existe apenas uma cidade para cada estado na array. Se você voltar no começo do post para conferir a array, verá que isso está certo.
 
Logo, é possível prever que o resultado final é `false`, porque *não há duas cidades no mesmo estado*. Para confirmar isso vou adicionar o último `if` no código:
 
```javascript
const result = maioresCidadesBrasil.some(function(cidade, index, array) {
  let quantidade = 0;
  
  for (i = 0; i < array.length; i++) {
    if (array[i].estado === cidade.estado) {
      quantidade = quantidade + 1;
    }
  }
  
  if (quantidade > 1) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // false
```
 
Para você compreender melhor o que aconteceu, mude o estado de alguma cidade para outro já existente. Por exemplo, coloque a propriedade `estado` de Porto Alegre para `"PE"`. Você verá que o resultado final mudará para `true`, porque agora sim *a array possui duas cidades no mesmo estado*.
 
Como já falei aqui no blog nos outros posts dessa série de métodos de array, não basta saber usar na teoria. É preciso entender o momento certo de aplicar cada um.
 
## Como saber quando usar o every e some em Javascript?
 
Não é em every momento que esses métodos são úteis, mas isso acontece some vezes.
 
![Escrita "laugh" em letra neon (risada em inglês)](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1653006346-tim-mossholder-imld5dbclm4-unsplash-1.jpg%3Fauto%3Dformat&w=3840&q=75)
 
Para saber que é o momento de usar o every e some em Javascript, siga esses 2 passos.
 
### Responder uma pergunta com "sim" ou "não"
 
Para começar, esses métodos são úteis em situações onde você precisa de um "sim" ou "não", verdadeiro ou falso, `true` ou `false` como resposta.
 
As perguntas seguem quase sempre esse modelo:
 
- **Every**: "Todos os itens dessa lista atendem aos requisitos?"
- **Some**: "Pelo menos um item dessa lista atende aos requisitos?"
 
Perceba que um simples "sim" ou "não" responde essas perguntas.
 
Isso é um ponto importante porque o retorno de every e some sempre é um booleano.
 
### Você já tem uma array
 
Every e some são métodos de array, então você precisa de uma para começar.
 
Não é possível usá-los com string, number ou objeto, a não ser que você os converta em array antes.
 
## Callback
 
Every e some são métodos de array em Javascript muito importantes.
 
Eles respondem perguntas com "sim" ou "não", ou `true` ou `false`.
 
O every responde se **todos os itens** de uma array atendem aos requisitos da função callback. Já o some diz se **pelo menos um item** da array atende aos requisitos.
 
Eles podem não iterar até o fim da array. Isso porque a resposta pode chegar antes. Se o every encontrar pelo menos 1 `false`, a resposta final é `false`. Da mesma forma, se o some encontrar pelo menos 1 `true`, a resposta final será `true`.
 
O retorno da função callback sempre será um valor booleano. Se o valor que você retornou não for um, o Javascript fará a coerção de tipo para garantir isso.
 
A função callback tem 3 parâmetros. O **item** de cada iteração, seu **índice** e a própria **array** que você está iterando.
 
Para saber o momento de usar every e some, preste atenção nesses dois requisitos. Primeiro, eles funcionam em situações onde você precisa responder uma pergunta com "sim" ou "não". E por último, você tem uma array para realizar essa operação.
 
De todos os artigos sobre métodos de array, esse foi um dos mais legais e mais trabalhosos. Porque foi o único com dois métodos no mesmo texto.
 
Se você perdeu os outros, veja aqui:
 
- [Como usar o forEach em Javascript: exemplos detalhados contados em uma história](https://demenezes.dev/posts/como-usar-foreach-javascript-exemplos/)
- [Transforme arrays em ouro: aprenda a manipular dados com o map() em Javascript](https://demenezes.dev/posts/map-javascript-array/)
- [Domine o método Filter e simplifique sua lógica com arrays em Javascript](https://demenezes.dev/posts/filter-javascript-array/)
- [O método find e a busca ao modo CTRL + F em JavaScript](https://demenezes.dev/posts/find-javascript-array/)
 
Além desse, ainda sairá o último artigo sobre o método reduce. Então aguarde só mais uns dias :) 
 
Obrigado pela sua leitura.
 
Ficou com alguma dúvida? Comente abaixo que será um prazer responder.
 
Se esse artigo te ajudou de alguma forma, e você sentiu vontade de dizer um **obrigado**, compartilhe com um amigo ou nas suas redes sociais.
 
Até mais.