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, 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:
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
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úmerofalse
", 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
.
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ávelmyProduct
- 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 atrue
- 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:
- Item: é o elemento da array daquela iteração
- Index: é o índice daquele item, começa em 0 e aumenta em 1 a cada iteração
- 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:
- Você precisa pegar um item de dentro de uma array
- Você já tem essa array "em mãos"
- 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!
Top comments (2)
Gostei bastante do artigo, dos códigos práticos, da comparação com a busca (Crtl + F), sempre muito bem explicado e ilustrado, não tinha conhecimento do terceiro parâmetro o array, achei bastante interessante. Muito obrigado por compartilhar seu conhecimento 🦤.
Sobre o
CTRL + F
, eu acho que sempre tem como comparar algo que tu tá ensinando (o conhecimento que a pessoa ainda não tem) com algo que a pessoa já conhece. Nesse caso, como a galera dev já usa computador e internet com frequência, é normal conhecer esse atalho.O terceiro parâmetro array é bem específico, eu nunca precisei usar ele em projeto real, acabou entrando no post mais como conhecimento mesmo. Com os dois primeiros parâmetros acho que já é possível fazer 99% das coisas.
:D