Arrays Avançados em JavaScript
Na lição anterior, você aprendeu operações básicas com arrays. Agora vamos subir de nível com "movimentos de poder" dos arrays — métodos de ordem superior. Estes permitem fazer mais com menos código e são habilidades essenciais no desenvolvimento JavaScript moderno.
map — Transformar Cada Elemento
map executa uma função em cada elemento e retorna um novo array — o original permanece inalterado. Pense nele como uma linha de montagem: cada elemento entra, é transformado e sai como parte de um novo produto.
<script>
let prices = [10, 20, 30];
let doubled = prices.map(p => p * 2); // [20, 40, 60]
</script>
O callback recebe três argumentos: (elemento, índice, arrayOriginal). Na maioria das vezes você só precisa do primeiro.
filter — Manter o Que Passa
filter mantém elementos que passam em um teste e retorna um novo array — o original não é tocado. Como um ponto de segurança: itens que atendem aos critérios passam; o resto é filtrado.
<script>
let scores = [45, 80, 92, 55, 78, 98];
let passed = scores.filter(s => s >= 60); // [80, 92, 78, 98]
</script>
Elementos onde o callback retorna true são mantidos; aqueles que retornam false são descartados.
reduce — Acumular em Um Valor Só
reduce "comprime" um array em um único valor. O caso de uso mais comum é somar:
<script>
let nums = [1, 2, 3, 4, 5];
let sum = nums.reduce((acc, cur) => acc + cur, 0); // 15
</script>
O que os parâmetros significam:
acc(acumulador): o total parcial, carregado da iteração anteriorcur(atual): o elemento atual- O segundo argumento
0é o valor inicial do acumulador
reduce parece complicado no início, mas sua essência é simples: passo a passo, comprima o array em um valor só. Soma, encontrar o máximo, contar ocorrências — resolve cuida de todos.
Exemplo: Combinando map, filter e reduce
<!DOCTYPE html>
<html lang="pt-br">
<body>
<h2>map / filter / reduce</h2>
<div id="output"></div>
<script>
let products = [
{ name: 'Notebook', price: 4999, category: 'Eletrônicos' },
{ name: 'Camiseta', price: 79, category: 'Roupas' },
{ name: 'Mouse', price: 149, category: 'Eletrônicos' },
{ name: 'Calça Jeans', price: 199, category: 'Roupas' },
{ name: 'Teclado', price: 299, category: 'Eletrônicos' }
];
let html = '<strong>Todos os Produtos:</strong><br>';
products.forEach(p => html += `${p.name} - R$${p.price} (${p.category})<br>`);
let electronics = products.filter(p => p.category === 'Eletrônicos');
html += '<br><strong>Eletrônicos (filter):</strong><br>';
electronics.forEach(p => html += `${p.name} - R$${p.price}<br>`);
let names = products.map(p => p.name);
html += '<br><strong>Nomes dos Produtos (map):</strong>' + names.join(', ') + '<br>';
let total = products.reduce((sum, p) => sum + p.price, 0);
html += '<br><strong>Preço Total (reduce):</strong>R$' + total;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
find e findIndex
find— retorna o primeiro elemento que correspondefindIndex— retorna o índice da primeira correspondência
Se nada for encontrado, find retorna undefined e findIndex retorna -1.
<script>
let users = [
{ name: 'Alice', age: 20 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 25 }
];
users.find(u => u.age > 22); // { name: 'Charlie', age: 25 }
users.findIndex(u => u.age < 18); // 1 (índice do Bob)
</script>
sort — Ordenar Elementos
sort organiza o array no local (modifica o original!). Por padrão, ordena como strings, o que engana muitos iniciantes:
<script>
let nums = [10, 1, 21, 2];
nums.sort(); // [1, 10, 2, 21] ← Ordenação de string! "10" < "2"
// Correto: ordenação numérica requer uma função comparadora
nums.sort((a, b) => a - b); // [1, 2, 10, 21] ← Crescente
nums.sort((a, b) => b - a); // [21, 10, 2, 1] ← Decrescente
</script>
sort muta o array original! Para manter o original intacto, copie primeiro: [...arr].sort(...).
Exemplo: Ordenando Notas de Alunos
<!DOCTYPE html>
<html lang="pt-br">
<body>
<h2>Ranking de Notas dos Alunos</h2>
<div id="output"></div>
<script>
let students = [
{ name: 'Alice', score: 72 },
{ name: 'Bob', score: 95 },
{ name: 'Charlie', score: 88 },
{ name: 'Diana', score: 61 },
{ name: 'Eve', score: 95 }
];
let html = '<strong>Ordem Original:</strong><br>';
students.forEach(s => html += `${s.name} - ${s.score}<br>`);
let byScore = [...students].sort((a, b) => b.score - a.score);
html += '<br><strong>Ordenado por Nota (Decrescente):</strong><br>';
byScore.forEach((s, i) => {
let medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : '';
html += `${medal} ${s.name} - ${s.score}<br>`;
});
let topStudents = students.filter(s => s.score >= 90);
html += '<br><strong>90 ou Acima (filter):</strong><br>';
topStudents.forEach(s => html += `${s.name} - ${s.score}<br>`);
let found = students.find(s => s.name === 'Charlie');
html += `<br><strong>Encontrar "Charlie" (find):</strong>${found ? found.score : 'Não encontrado'}`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
some e every
some— pelo menos um elemento passa no teste? (retorna um booleano)every— todos os elementos passam no teste? (retorna um booleano)
<script>
let scores = [60, 75, 82, 90];
scores.some(s => s >= 90); // true — alguém tirou 90+
scores.some(s => s === 100); // false — ninguém tirou nota perfeita
scores.every(s => s >= 60); // true — todos passaram
</script>
some pergunta "existe alguém que...", enquanto every pergunta "todos...". Um verifica existência; o outro verifica completude.
Operador Spread (...)
O operador spread ... "desempacota" um array. É comumente usado para copiar e mesclar:
<script>
let a = [1, 2, 3];
let b = [...a]; // Cópia: [1, 2, 3] (novo array, não uma referência)
let c = [...a, 4, 5]; // Mesclagem: [1, 2, 3, 4, 5]
let d = [0, ...a, 4]; // Inserção: [0, 1, 2, 3, 4]
let x = [1, 2], y = [3, 4];
let z = [...x, ...y]; // [1, 2, 3, 4]
</script>
Desestruturação
Extraia valores de um array e atribua-os a variáveis por posição:
<script>
let [a, b, c] = [1, 2, 3];
// a = 1, b = 2, c = 3
let [first, ...rest] = [1, 2, 3, 4, 5];
// first = 1, rest = [2, 3, 4, 5]
let [nome, nota] = ['Alice', 95];
// nome = 'Alice', nota = 95
</script>
Encadeamento de Métodos
Métodos de ordem superior retornam novos arrays, então você pode encadeá-los um após o outro:
<script>
let result = students
.filter(s => s.score >= 60) // Primeiro, filtra alunos aprovados
.map(s => s.name) // Depois, extrai nomes
.sort(); // Por fim, ordena
</script>
Exemplo: Encadeamento para Processar Dados
<!DOCTYPE html>
<html lang="pt-br">
<body>
<h2>Encadeamento de Métodos</h2>
<div id="output"></div>
<script>
let employees = [
{ name: 'Alice', dept: 'Engenharia', salary: 8000 },
{ name: 'Bob', dept: 'Vendas', salary: 5000 },
{ name: 'Charlie', dept: 'Engenharia', salary: 12000 },
{ name: 'Diana', dept: 'Vendas', salary: 6500 },
{ name: 'Eve', dept: 'Engenharia', salary: 10000 },
{ name: 'Frank', dept: 'Marketing', salary: 5500 }
];
let html = '<strong>Todos os Funcionários:</strong><br>';
employees.forEach(e => html += `${e.name} | ${e.dept} | R$${e.salary}<br>`);
let techHighSalary = employees
.filter(e => e.dept === 'Engenharia')
.filter(e => e.salary >= 9000)
.map(e => `${e.name}(R$${e.salary})`);
html += '<br><strong>Engenheiros de Alto Salário (filter+map encadeado):</strong><br>' + techHighSalary.join(', ');
let avgSalary = employees
.filter(e => e.dept === 'Engenharia')
.map(e => e.salary)
.reduce((sum, s) => sum + s, 0);
let count = employees.filter(e => e.dept === 'Engenharia').length;
html += `<br><br><strong>Salário Médio de Engenharia:</strong>R$${(avgSalary / count).toFixed(0)}`;
let allAbove3k = employees.every(e => e.salary > 3000);
let has12k = employees.some(e => e.salary >= 12000);
html += `<br><br><strong>Todos os salários > R$3000?</strong>${allAbove3k ? 'Sim' : 'Não'}`;
html += `<br><strong>Alguém ganha ≥ R$12000?</strong>${has12k ? 'Sim' : 'Não'}`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
Exemplo: Operador Spread e Desestruturação
<!DOCTYPE html>
<html lang="pt-br">
<body>
<h2>Operador Spread e Desestruturação</h2>
<div id="output"></div>
<script>
let a = [1, 2, 3];
let b = [...a];
b.push(4);
let html = `<strong>Copiando com Spread:</strong><br>`;
html += `Array original a: [${a}]<br>`;
html += `Cópia b: [${b}]<br>`;
html += `Modificar b não afeta a<br><br>`;
let x = [1, 2], y = [3, 4];
let merged = [...x, ...y, 5];
html += `<strong>Array Mesclado:</strong>[${merged}]<br><br>`;
let [first, second, ...rest] = [10, 20, 30, 40, 50];
html += `<strong>Desestruturação:</strong><br>`;
html += `first = ${first}<br>`;
html += `second = ${second}<br>`;
html += `rest = [${rest}]<br><br>`;
let scores = [85, 92, 78, 95, 60];
let [highest, ...others] = [...scores].sort((a, b) => b - a);
html += `<strong>Desestruturação + Sort:</strong><br>`;
html += `Maior = ${highest}<br>`;
html += `Outros = [${others}]`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
📖 Resumo
maptransforma cada elemento em um novo array,filtermantém elementos correspondentes,reduceacumula em um único valorfindretorna o primeiro elemento correspondente,findIndexretorna o primeiro índice correspondentesortpor padrão ordena como string — para números, sempre passe um comparador:(a, b) => a - bsomeverifica se algum elemento corresponde,everyverifica se todos os elementos correspondem- O operador spread
...copia e mescla arrays; desestruturação extrai elementos em variáveis - Métodos de ordem superior retornam novos arrays e podem ser encadeados para código conciso e legível
❓ Perguntas Frequentes
P:Qual a diferença entre
mapeforEach? R:mapretorna um novo array;forEachretornaundefined. Usemapquando precisar do resultado,forEachquando só quer executar uma ação. Não façapushmanual dentro deforEach— para isso serve omap.
P:Por que
sortmodifica o array original? R:É uma escolha de design histórica.sorté uma operação no local — reorganiza os elementos em vez de retornar um novo array. Para preservar o original, copie primeiro:[...arr].sort(...).
P:Posso omitir o valor inicial no
reduce? R:Sim — se omitido, o primeiro elemento se torna o valor inicial e a iteração começa do segundo. Mas um array vazio sem valor inicial lançará um erro, então sempre forneça um por segurança.
📝 Atividades
- Dado o array
[3, 8, 12, 5, 9, 17, 4], usefilterpara manter números maiores que 7, depoismappara dobrá-los. Exiba o resultado. - Use
reducepara contar a ocorrência de cada palavra em um array como['maçã', 'banana', 'maçã', 'cereja', 'banana', 'maçã']→{ maçã: 3, banana: 2, cereja: 1 }. - Dado um array de alunos (com
nomeenota), use encadeamento para: filtrar alunos aprovados → ordenar por nota decrescente → extrair nomes em um novo array. Exiba o resultado na página.



