O método find e a busca ao modo CTRL + F em JavaScript

O método find em Javascript é um dos mais simples de entender, porque ele funciona muito igual ao atalho CTRL+F. Não acredita? Clique e veja

  • find
  • javascript
  • array
Front-end

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, 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
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:

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. 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:

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:

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:

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:

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

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
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:

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:

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:

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:

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:

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:

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:

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:

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:

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:

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.

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.

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!

Veja outros posts sobre Front-end