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 usar delete 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() e findLast() (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() e findLastIndex(): Devolvem o índice posicional ou -1.
  • some() e every(): Avaliação booleana em curto-circuito:
    • some() cessa a execução no primeiro true.
    • every() cessa a execução no primeiro false.
  • 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"]