Arrays são estruturas de dados fundamentais em JavaScript, e dominar seus métodos é essencial para escrever código eficiente e expressivo. Nesta aula, vamos explorar três grupos de métodos essenciais: os que adicionam/removem elementos nas extremidades (push, pop, shift, unshift), os que extraem ou removem partes do array (slice e splice), e os que buscam elementos (indexOf e includes). Compreender as diferenças e usos corretos de cada um evitará bugs comuns e melhorará a legibilidade do seu código.

push/pop/shift/unshift

Estes quatro métodos permitem manipular as extremidades de um array de forma simples e eficiente. push adiciona um ou mais elementos ao final do array e retorna o novo comprimento. pop remove o último elemento e o retorna. unshift adiciona elementos ao início, deslocando os existentes, e retorna o novo comprimento. shift remove o primeiro elemento e o retorna.

Exemplo prático:

let arr = [1, 2, 3];

// push
let newLength = arr.push(4, 5);
console.log(arr);       // [1, 2, 3, 4, 5]
console.log(newLength); // 5

// pop
let removed = arr.pop();
console.log(arr);    // [1, 2, 3, 4]
console.log(removed); // 5

// unshift
newLength = arr.unshift(0);
console.log(arr);       // [0, 1, 2, 3, 4]
console.log(newLength); // 5

// shift
removed = arr.shift();
console.log(arr);    // [1, 2, 3, 4]
console.log(removed); // 0

Esses métodos modificam o array original (são mutáveis). push e pop são muito rápidos (O(1)), enquanto unshift e shift são O(n) porque precisam reindexar todos os elementos. Prefira push/pop para filas (FIFO) e shift/unshift com cautela em arrays grandes.

slice vs splice

À primeira vista, slice e splice podem parecer similares, mas têm propósitos bem diferentes. slice é usado para extrair uma cópia de uma parte do array sem modificar o original. splice é usado para adicionar, remover ou substituir elementos no array original, modificando-o.

slice: Recebe dois índices (início, fim) e retorna um novo array com os elementos do índice início até (mas não incluindo) fim. Se fim for omitido, vai até o final. Índices negativos contam a partir do final.

let arr = [10, 20, 30, 40, 50];
let sliced = arr.slice(1, 3);
console.log(sliced); // [20, 30]
console.log(arr);    // [10, 20, 30, 40, 50] (inalterado)

// cópia rasa do array inteiro
let copy = arr.slice();

splice: Recebe índice inicial, quantidade de elementos a remover (opcional, 0 se não quiser remover), e itens a adicionar (opcional). Retorna um array com os elementos removidos. Modifica o array original.

let arr = [10, 20, 30, 40, 50];

// Remove 2 elementos a partir do índice 1
let removed = arr.splice(1, 2);
console.log(removed); // [20, 30]
console.log(arr);     // [10, 40, 50]

// Adiciona sem remover (deleteCount = 0)
arr.splice(1, 0, 25, 35);
console.log(arr); // [10, 25, 35, 40, 50]

// Substituir (remove 1, adiciona 2)
arr.splice(2, 1, 99);
console.log(arr); // [10, 25, 99, 40, 50]

Use slice quando quiser uma cópia ou subarray imutável. Use splice quando precisar modificar o array original (remover/inserir no meio).

indexOf / includes

Para buscar elementos em um array, temos indexOf e includes. Ambos usam comparação estrita (===). indexOf retorna o índice da primeira ocorrência do elemento, ou -1 se não existir. includes retorna um booleano indicando se o elemento está presente.

let arr = [1, 2, 3, 2, 1];

console.log(arr.indexOf(2));    // 1
console.log(arr.indexOf(4));    // -1
console.log(arr.indexOf(2, 2)); // 3 (a partir do índice 2)

console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false

includes é mais legível quando você só quer saber se o elemento existe. indexOf é útil quando você precisa da posição para remover ou substituir. Ambos percorrem o array linearmente (O(n)).

Boas práticas: Use includes para condições simples, como if (arr.includes(valor)). Para arrays de objetos, lembre-se que a comparação é por referência; use find ou findIndex nesses casos.

Referências

Exercícios

  1. Qual a diferença entre slice e splice em relação à mutabilidade do array original?

    ✓ Resposta: slice não modifica o array original (retorna um novo array). splice modifica o array original (adiciona, remove ou substitui elementos).
  2. O que retorna arr.push(1)?

    ✓ Resposta: Retorna o novo comprimento do array após a adição.
  3. Dado let arr = ['a', 'b', 'c', 'd', 'e'], use splice para remover 'c' e 'd' e inserir 'x' e 'y' no lugar. Escreva o código e o estado final de arr.

    ✓ Resposta:
    let arr = ['a', 'b', 'c', 'd', 'e'];
    arr.splice(2, 2, 'x', 'y');
    console.log(arr); // ['a', 'b', 'x', 'y', 'e']
  4. Qual método você usaria para verificar se o número 42 existe em um array, e qual a diferença para indexOf?

    ✓ Resposta: Use includes para obter um booleano. indexOf retorna o índice ou -1, sendo útil quando você precisa da posição.
  5. Explique por que unshift é mais lento que push em arrays grandes.

    ✓ Resposta: unshift precisa deslocar todos os elementos existentes para a direita para abrir espaço no início, resultando em complexidade O(n). push apenas adiciona ao final, que é O(1) (amortizado).