📊 Capítulo 05: Arrays Modernos, Métodos Funcionais e Imutabilidade
Módulo 05: JavaScript Moderno (ES6+) e DOM • Bloco 2: Estruturas de Dados & POO
🗺️ Mapa Conceitual do Capítulo
flowchart TD
subgraph V8_ARRAY_ENGINE["Arquitetura de Arrays no Motor V8"]
FAST["Fast Elements (Packed Arrays)\nArmazenamento contíguo em C++ · Acesso O(1) ultrarrápido"]
SLOW["Slow Elements (Dictionary Mode)\nTabela Hash · Queda de performance ao introduzir buracos (Holes)"]
FAST -.->|"delete arr[i] ou arr[50000] = x"| SLOW
end
subgraph FUNCTIONAL_TRILOGY["A Tríade Funcional Imutável"]
DATA["Array Original (Imutável)"]
FILTER["1. filter(predicate)\n(Seleção booleana N -> M, onde M <= N)"]
MAP["2. map(transform)\n(Transformação pura 1:1, N -> N)"]
REDUCE["3. reduce(reducer, initialValue)\n(Consolidação N -> 1 valor, objeto agrupado ou estrutura)"]
DATA --> FILTER --> MAP --> REDUCE
end
subgraph ES2023_BY_COPY["A Nova Geração Imutável (Change by Copy - ES2023)"]
MUT["Métodos Mutativos Legados (In-Place)\nsort() · reverse() · splice() · arr[i] = x"]
PURE["Métodos Puros Modernos (By Copy)\ntoSorted() · toReversed() · toSpliced() · with()"]
MUT -.->|"Substituição Defensiva"| PURE
end
⚡ 1. Anatomia de Baixo Nível: Como o V8 Executa Arrays
Em linguagens como C ou Java, um array é um bloco sequencial contíguo de bytes de tipo homogêneo. No JavaScript, arrays são objetos especializados onde os índices numéricos são chaves. Para manter velocidade extrema, o motor V8 implementa estratégias de otimização interna:
- Packed Elements (Fast Elements): Quando o array possui dados contínuos sem saltos (índices 0, 1, 2…). O V8 aloca um buffer sequencial de memória nativa em C++, garantindo complexidade de leitura e escrita $\mathcal{O}(1)$:
PACKED_SMI_ELEMENTS: Contém exclusivamente inteiros pequenos (Small Integers de 31 bits).PACKED_DOUBLE_ELEMENTS: Contém números de ponto flutuante.PACKED_ELEMENTS: Contém referências heterogêneas a objetos ou strings.
- Holey Elements (Slow Elements): Se você criar “buracos” no array (ex.:
const arr = []; arr[1000] = 'teste';ou usardelete arr[1]), o V8 é forçado a abandonar a memória contígua e transitar para Dictionary Mode (uma Hash Table esparsa), degradando a performance em até 10 vezes.
🔁 2. A Tríade Funcional: filter(), map() e reduce()
O paradigma funcional prioriza funções puras que transformam coleções sem gerar efeitos colaterais (Side Effects):
const produtos = [
{ id: 1, nome: "Teclado Mecânico", categoria: "Periféricos", preco: 350, estoque: 12 },
{ id: 2, nome: "Mouse Óptico", categoria: "Periféricos", preco: 180, estoque: 0 },
{ id: 3, nome: "Monitor 27 4K", categoria: "Monitores", preco: 2200, estoque: 5 },
{ id: 4, nome: "Cabo HDMI 2.1", categoria: "Acessórios", preco: 60, estoque: 45 }
];
// Pipeline Funcional Declarativo Encadeado:
const resumoPerifericos = produtos
// 1. filter: Isola apenas itens disponíveis da categoria
.filter(p => p.categoria === "Periféricos" && p.estoque > 0)
// 2. map: Aplica desconto de 10% e projeta novo modelo de dados
.map(p => ({
produto: p.nome,
valorComDesconto: p.preco * 0.9,
faturamentoEstimado: (p.preco * 0.9) * p.estoque
}))
// 3. reduce: Totaliza o faturamento potencial da categoria
.reduce((acumulador, item) => acumulador + item.faturamentoEstimado, 0);
console.log(resumoPerifericos); // Faturamento total calculado
O Poder do reduce() em Casos Complexos: GroupBy Customizado
Antes da introdução recente de Object.groupBy(), o reduce() já era a ferramenta universal para agrupar coleções:
const produtosPorCategoria = produtos.reduce((grupos, produto) => {
const chave = produto.categoria;
grupos[chave] ??= [];
grupos[chave].push(produto);
return grupos;
}, {});
🔍 3. Métodos Avançados de Busca: find(), findLast() e flatMap()
find()efindLast()(ES2023): Retornam o primeiro ou último elemento que satisfaz a condição (interrompendo a varredura no momento do match, sem percorrer o array inteiro).findIndex()efindLastIndex(): Devolvem o índice posicional ou-1.some()eevery(): Avaliação booleana em curto-circuito:some()cessa a execução no primeirotrue.every()cessa a execução no primeirofalse.
flatMap(): Aplica uma transformação e achata o array resultante em exatamente um nível em uma única iteração, sendo muito mais eficiente que encadear.map().flat().
const usuariosComTags = [
{ nome: "Ana", tags: ["frontend", "react"] },
{ nome: "Bruno", tags: ["backend", "node"] }
];
// flatMap extrai todas as tags em um array linear plano:
const todasTags = usuariosComTags.flatMap(u => u.tags);
// ["frontend", "react", "backend", "node"]
🛡️ 4. A Revolução do ES2023: Métodos Imutáveis (Change Array by Copy)
Historicamente, métodos fundamentais do JavaScript mutavam o array original diretamente na memória, causando bugs severos em arquiteturas de componentes reativos (React, Vue) e em fluxos com Redux. O padrão ES2023 introduziu alternativas puras:
| Operação | Método Mutativo Legado (In-Place) | Método Puro Moderno (By Copy - ES2023) |
|---|---|---|
| Ordenação | arr.sort((a, b) => a - b) (Muta o original) |
const novo = arr.toSorted((a, b) => a - b) |
| Inversão | arr.reverse() (Muta o original) |
const novo = arr.toReversed() |
| Corte e Inserção | arr.splice(1, 2, 'novo') (Muta o original) |
const novo = arr.toSpliced(1, 2, 'novo') |
| Substituição de Índice | arr[2] = 'novo' (Muta o original) |
const novo = arr.with(2, 'novo') |
const linguagens = ["JavaScript", "Python", "Rust", "Go"];
// Ordenação funcional pura sem efeitos colaterais no array fonte:
const linguagensOrdenadas = linguagens.toSorted();
const linguagensInvertidas = linguagens.toReversed();
const substituido = linguagens.with(1, "TypeScript");
console.log(linguagens); // ["JavaScript", "Python", "Rust", "Go"] (Preservado!)
console.log(substituido); // ["JavaScript", "TypeScript", "Rust", "Go"]