O método find e a busca ao modo CTRL + F em JavaScript
Tags: find, javascript, array, githubbrasil
Published: 2023-11-02 11:30:05

## O método find em Javascript é um dos mais simples de entender, porque ele funciona muito igual ao atalho CTRL+F
 
Qual é a melhor ferramenta do mundo?
 
Claro que é o `CTRL + F`.
 
Quase todos os programas que uso (pelo menos os que respeito) permitem fazer uma busca. Seja:
 
- Buscar texto em uma página web
- Buscar arquivos ou outras informações em um banco de dados
 
O próprio VS Code permite buscar um termo em todos os arquivos do projeto atual, é mágico. Aqui tem uma série de [atalhos do VS Code](https://demenezes.dev/posts/atalhos-vs-code-aumentar-produtividade/), caso você se interesse.
 
Se esse recurso é familiar para você, vai ser bem fácil entender esse artigo. **O find do encontra o primeiro item dentro de uma array que atende a um ou mais critérios e retorna esse item**.
 
Veja um exemplo:
 
![representação gráfica de um find simples em javascript](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1698714568-representacao-grafica-de-um-find-simples-em-javascript.png%3Fauto%3Dformat&w=3840&q=75)
 
```javascript
const numbers = [ 0, 3, 1, 6, 3, 7, 5 ];

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

console.log(result); // 6
```
 
Veja que o find não retorna uma array `[ 6 ]`, e sim o item `6` sozinho. Já que 6 é o primeiro item acima de 5, o find retorna ele e pára a execução.
 
Por outro lado, se a array for composta por outras arrays, é claro que o retorno será uma array:
 
```javascript
const arrays = [
  [ 'array de' ,'dois itens' ],
  [ 'array de' ,'três', 'itens' ],
  [ 'array', 'grandona', 'de', '5', 'itens']
];

const result = arrays.find(function(array) {
  if (array.length > 2) {
    return true;
  } else {
    return false;
  }
});

console.log(result); // [ 'array de' ,'três', 'itens' ]
```
 
O exemplo acima retorna uma array de 3 itens, porque ele é um item único dentro da array que você executou o find. Só por isso.
 
Caso você precise de **todos os itens** em uma array que atenda a um ou mais requisitos, prefira usar o [método filter em Javascript](https://demenezes.dev/posts/filter-javascript-array/). Esse sim vai retornar um array.
 
Agora que você tem uma visão geral sobre o método find, veja mais alguns pontos importantes.
 
## Estrutura do método find em Javascript
 
Foco na função callback.
 
O método find recebe uma função callback como parâmetro, e retorna `true` quando encontrar o item que procura.
 
No exemplo da array de números, a função callback é esse trecho:
 
```javascript
function(number) {
  if (number > 5) {
    return true;
  } else {
    return false;
  }
}
```
 
Perceba que chamei o parâmetro dela de `number`. A cada iteração, essa variável aponta para um item diferente da array original.
 
**Logo após encontrar o item, o find pára de executar**, o que é ótimo para performance. Para mostrar isso, vou colocar um `console.log()` a cada iteração:
 
```javascript
const numbers = [ 0, 3, 1, 6, 3, 7, 5 ];

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

console.log(result);

/* ************************
  
  O número atual é: 0
  O número atual é: 3
  O número atual é: 1
  O número atual é: 6
  6

************************ */
```
 
Repare que o resultado coloca no console apenas os números até o 6, pois é ele que atende ao requisito de ser maior que 5. Durante todos esses consoles, o find caiu no `else`, ou seja, `return false`. Assim que o número 6 surgiu, por ser maior que 5 o find caiu no `return true` e os próximos consoles não executaram.
 
Percebeu a importância do retorno da função callback? E é dela que vou falar agora.
 
## O retorno da função callback do find
 
O retorno dela sempre será um booleano.
 
Isso fica claro nos exemplos, pois sempre coloco `return true` ou `return false`. Mas e se eu escrever assim:
 
```javascript
const numbers = [ 0, 3, 1, 6, 3, 7, 5 ];

const result = numbers.find(function(number) {
  return number > 6;
});

console.log(result); // 7
```
 
Eu não retornei um booleano diretamente, e sim a expressão lógica `number > 6`. Ou seja, quando a variável `number` estiver acima de 6, esse será o valor que o find retornará. E o resultado é 7.
 
E se eu for além:
 
```javascript
const numbers = [ 0, 3, 1, 6, 3, 7, 5 ];

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

console.log(result); // 3
```
 
![representação gráfica de um find com coerção de tipo](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1698714655-representacao-grafica-de-um-find-com-coercao-de-tipo.png%3Fauto%3Dformat&w=3840&q=75)
 
Ficou um pouco estranho, mas é tranquilo de entender. **A linha `return number` converte a variável `number` (que é do tipo number) para o tipo boolean**, e assim poder funcionar.
 
- Na primeira iteração, acontece `return 0`, e já que zero é o único "número `false`", o find prossegue
- Na segunda iteração, acontece `return 3`, que vira "`return true`", e esse é o resultado
 
Essa conversão de number para boolean se chama coerção de tipo, um tópico muito importante em Javascript. Recomendo que você estude.
 
E se o find não encontrar o que deseja? O retorno será `undefined`.
 
![representação gráfica de um find retornando undefined](https://demenezes.dev/_next/image/?url=https%3A%2F%2Fwww.datocms-assets.com%2F64896%2F1698714599-representacao-grafica-de-um-find-retornando-undefined.png%3Fauto%3Dformat&w=3840&q=75)
 
```javascript
const numbers = [ 0, 3, 1, 6, 3, 7, 5 ];

const result = numbers.find(function(number) {
  return number > 10;
});

console.log(result); // undefined
```
 
Você percebeu que em todos os exemplos, a função callback recebeu apenas 1 parâmetro? Essa função pode receber até 3 parâmetros. E vou mostrar cada um deles agora.
 
## Parâmetros da função callback do find
 
Hora dos desafios!
 
Vou deixar um desafio para você entender cada parâmetro que eu explicar. A array abaixo vai servir de exemplo para todos os desafios:
 
```javascript
const products = [
  { id: '1a2b3c4d', name: 'Camiseta Básica', color: 'Branca', size: 'M',     weight: 200, availability: true  },
  { id: '5e6f7g8h', name: 'Calça Jeans',     color: 'Azul',   size: 'L',     weight: 500, availability: true  },
  { id: '9i0j1k2l', name: 'Bolsa de Couro',  color: 'Marrom', size: 'Único', weight: 800, availability: false },
  { id: '3m4n5o6p', name: 'Tênis Esportivo', color: 'Preto',  size: '42',    weight: 300, availability: true  },
  { id: '7q8r9s0t', name: 'Vestido Floral',  color: 'Rosa',   size: 'S',     weight: 350, availability: true  }
];
```
 
Veja o primeiro parâmetro.
 
### Parâmetro item
 
Esse parâmetro você já conhece, mas será legal de revisar com um desafio.
 
Veja: *encontre na array de produtos, aquele que tem o ID "3m4n5o6p"*.
 
Se você não caiu nesse capítulo do post de paraquedas, já sabe como resolver esse desafio:
 
```javascript
const result = products.find(function(product) {
  if (product.id === '3m4n5o6p') {
    return true;
  } else {
    return false;
  }
});

/*
  Ou de uma forma mais curta:
  const result = products.find(product => product.id === '3m4n5o6p');
*/

console.log(result);

/*
  {
    id: '3m4n5o6p',
    name: 'Tênis Esportivo',
    color: 'Preto',
    size: '42',
    weight: 300,
    availability: true
  }
*/
```
 
A função callback retorna o primeiro produto que tiver a propriedade `id` igual a `"3m4n5o6p"`.
 
Essa aplicação do find é muito comum na vida real: pegar um item através de um identificar único. Veja o exemplo abaixo:
 
```javascript
function getProductById(id) {
  return products.find(product => product.id === id);
}

const myProduct = getProductById('9i0j1k2l');

console.log(myProduct);

/*
  {
    id: '9i0j1k2l',
    name: 'Bolsa de Couro',
    color: 'Marrom',
    size: 'Único',
    weight: 800,
    availability: false
  }
*/
```
 
O que aconteceu aqui foi o seguinte;
 
- Criei a função `getProductByID` que pega um produto do banco de dados pelo ID
- Essa função recebe um ID específico no parâmetro e usa o método find exatamente como no exemplo anterior
- Depois executo essa função com o argumento `"9i0j1k2l"` e coloco o retorno na variável `myProduct`
- Essa variável recebe as informações do produto Bolsa de Couro
 
Veja agora o próximo parâmetro do find em Javascript.
 
### Parâmetro index
 
O parâmetro index é um número, mas não qualquer número.
 
**Na primeira iteração, ele é 0, depois 1, depois 2, depois 3**... Você entendeu né?
 
Ele representa o índice de cada item da array original:
 
```javascript
const result = products.find(function(product, index) {
  if (index === 0) {
    return true;
  } else {
    return false;
  }
});

console.log(result);

/*
  {
    id: '1a2b3c4d',
    name: 'Camiseta Básica',
    color: 'Branca',
    size: 'M',
    weight: 200,
    availability: true
  }
*/
```
 
O exemplo acima busca o item que tem o index igual a 0. É claro que esse código é desnecessário. Seria mais fácil escrever apenas `products[0]`, mas a intenção é mostrar a aplicação do index.
 
O desafio agora é: *encontre um produto que esteja disponível na loja, porém seu index não pode ser 0 nem 1*.
 
Na vida real, esse tipo de critério é bem difícil de acontecer, mas isso serve para você ver uma das aplicações possíveis do parâmetro index.
 
Então os critérios são dois:
 
- Produto disponível: vou usar a propriedade `available` igual a `true`
- Index diferente de 1: vou usar o parâmetro `index` e `!== 0` e `!== 1`
 
O código fica assim:
 
```javascript
const result = products.find(function(product, index) {
  if (product.availability === true && index !== 0 && index !== 1) {
    return true;
  } else {
    return false;
  }
});

console.log(result);

/*
  {
    id: '3m4n5o6p',
    name: 'Tênis Esportivo',
    color: 'Preto',
    size: '42',
    weight: 300,
    availability: true
  }
*/
```
 
Bem parecido com os desafios anteriores. As condições de disponibilidade e índice estão dentro do `if`, e se o retorno será `true` ou `false` depende do resultado dessa operação lógica.
 
Por fim, veja agora o último parâmetro da função callback do find.
 
### Parâmetro array
 
Esse é o terceiro parâmetro.
 
Veja ele no exemplo abaixo:
 
```javascript
const result = products.find(function(product, index, array) {
  
});
```
 
**Esse parâmetro não varia a cada iteração, ele tem sempre o mesmo valor: a array que você está iterando**. Nesse exemplo ele sempre será a lista com as informações dos produtos.
 
Sugiro que você não use esse parâmetro para alterar a lista, apenas consultá-la para outras operações.
 
E é aí que entra o desafio: *encontre o primeiro item da array que tenha um valor na propriedade `availability` que nenhum outro item tem*. Ou seja, só vai retornar `true` quando o valor dessa propriedade não se repetir em outro elemento.
 
Para começar, vou pegar o valor dessa propriedade:
 
```javascript
const result = products.find(function(product, index, array) {
  const availability = product.availability;
});
```
 
Agora preciso descobrir se o valor de `availability` em cada iteração é único ou se repete na array. Para isso, vou criar uma variável `quantity` que irá contar a quantidade desse valor na array:
 
```javascript
const result = products.find(function(product, index, array) {
  const availability = product.availability;
  
  let quantity = 0;
});
```
 
Ela inicia em 0, e agora vou incrementar ela. Para isso, vou fazer um `for` na array e incrementar o valor dessa variável quando o `availability` dos outros produtos for igual ao atual:
 
```javascript
const result = products.find(function(product, index, array) {
  const availability = product.availability;
  
  let quantity = 0;
  for (let i = 0; i < array.length; i++) {
    if (array[i].availability === availability) {
      quantity = quantity + 1;
    }
  }
  console.log(quantity);
});
```
 
Na penúltima linha, coloquei um console para ver o valor dessa variável. O resultado é esse:
 
```
4
4
1
4
4
```
 
Os seja nas duas primeiras iterações (produtos *Camiseta Básica* e *Calça Jeans*), o valor da propriedade `availability` deles se repete 4 vezes na array. Esse valor é `true`. Na terceira iteração (produto *Bolsa de Couro*), o valor é 1, porque só existe um produto com `availability: false`. Na duas últimas iterações, novamente você vê que o número 4 se repete, pois são dois produtos com `availability: true`, *Tênis Esportivo* e *Vestido Floral*.
 
Logo, *o único produto da array que tem um valor na propriedade `availability` que nenhum outro produto tem*, é o da terceira iteração. Ou seja, Bolsa de Couro.
 
Agora vou fazer a prova real para ver se essa realmente é a resposta do desafio:
 
```javascript
const result = products.find(function(product, index, array) {
  const availability = product.availability;
  
  let quantity = 0;
  for (let i = 0; i < array.length; i++) {
    if (array[i].availability === availability) {
      quantity = quantity + 1;
    }
  }
  
  if (quantity === 1) {
    return true;
  } else {
    return false;
  }
});

console.log(result);

/*
  {
    id: '9i0j1k2l',
    name: 'Bolsa de Couro',
    color: 'Marrom',
    size: 'Único',
    weight: 800,
    availability: false
  }
*/
```
 
E é isso mesmo.
 
---
 
Como sempre digo por aqui, não basta saber a teoria e os comandos das linguagens, é preciso saber o momento de usar.
 
## Quando usar o find
 
Aqui, não tem muito mistério.
 
### O que você precisa?
 
A resposta para essa pergunta é *"eu preciso de um item de dentro de uma array"*.
 
Isso significa que você tem uma array e precisa pegar **apenas um item** de dentro dela.
 
Caso você precise de mais de um item, use o [método filter](https://demenezes.dev/posts/filter-javascript-array/).
 
### O que você tem?
 
Aqui, a resposta é mais óbvia ainda: **uma array**.
 
Se você quer um item de dentro de uma array, obviamente precisa ter uma array.
 
Se você tiver algo que não é uma array, como um objeto, converta para uma array antes .
 
### O item que você precisa é exatamente aquele dentro da array?
 
A resposta precisa ser **sim**.
 
O método find não altera o item. Mas nada impede de você alterá-lo depois que o find terminar de executar.
 
## Callback
 
Em resumo: é um `CTRL + F`.
 
O método find busca e retorna de dentro de uma array o primeiro valor que corresponde aos critérios que você definir. Se não encontrar, o retorno será `undefined`.
 
O find retorna sempre o primeiro item, mesmo que mais de um item atenda aos critérios. Se você precisar de mais de um item, use o [método filter](https://demenezes.dev/posts/filter-javascript-array/).
 
Dentro da função callback você define os critérios e retorna um valor booleano. Se for `true`, o find retorna aquele valor e finaliza a execução. Se for `false`, avança para o próximo.
 
Mesmo que você não retorne um booleano de forma explícita, o Javascript realiza a coerção de tipo para garantir isso.
 
A função callback recebe até 3 parâmetros:
 
1. **Item**: é o elemento da array daquela iteração
2. **Index**: é o índice daquele item, começa em 0 e aumenta em 1 a cada iteração
3. **Array**: seu valor é sempre a array que você está iterando
 
Para saber que é o momento de usar o find, você precisa dar match com esses três requisitos:
 
1. Você precisa pegar um item de dentro de uma array
2. Você já tem essa array "em mãos"
3. Você precisa daquele item original, sem alterações
 
O método find do Javascript, além do filter que já mencionei algumas vezes ao longo do post, é muito útil no dia a dia. E minha intenção aqui foi passar de forma direta a grande maioria das possibilidades com ele.
 
Se esse conteúdo te ajudou, e você sente vontade de dizer um **obrigado**, compartilhe nas redes sociais ou com algum amigo :) 
 
Até a próxima!