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 métodos que permitem adicionar, remover e buscar elementos, além de entender as diferenças entre operações que parecem similares, como slice e splice.

Você aprenderá não apenas a sintaxe, mas também quando usar cada método, evitando armadilhas comuns. Vamos começar com os métodos de manipulação de extremidades.

push/pop/shift/unshift

Esses quatro métodos permitem adicionar ou remover elementos no início ou no final do array. São operações de complexidade O(1) para push e pop (fim), mas O(n) para shift e unshift (início), pois todos os índices precisam ser atualizados.

  • push(elemento1, ..., elementoN): adiciona um ou mais elementos ao final do array e retorna o novo comprimento.
  • pop(): remove o último elemento do array e o retorna. Se o array estiver vazio, retorna undefined.
  • unshift(elemento1, ..., elementoN): adiciona um ou mais elementos ao início do array e retorna o novo comprimento.
  • shift(): remove o primeiro elemento do array e o retorna. Se vazio, retorna undefined.

Exemplo:

let arr = ['a', 'b', 'c'];

// push
let newLength = arr.push('d', 'e');
console.log(arr);        // ['a', 'b', 'c', 'd', 'e']
console.log(newLength);  // 5

// pop
let removed = arr.pop();
console.log(removed);    // 'e'
console.log(arr);        // ['a', 'b', 'c', 'd']

// unshift
newLength = arr.unshift('x', 'y');
console.log(arr);        // ['x', 'y', 'a', 'b', 'c', 'd']
console.log(newLength);  // 6

// shift
removed = arr.shift();
console.log(removed);    // 'x'
console.log(arr);        // ['y', 'a', 'b', 'c', 'd']

Boas práticas: Prefira push e pop para operações frequentes em arrays grandes, pois são mais rápidos. Evite shift e unshift em loops com muitos elementos; considere usar uma estrutura de dados diferente (como deque) se precisar de inserções/remoções no início.

slice vs splice

Ambos os métodos operam em partes do array, mas com propósitos diferentes: slice cria uma cópia superficial de uma parte do array sem modificar o original, enquanto splice modifica o array removendo, substituindo ou adicionando elementos.

slice(início, fim): Retorna um novo array contendo os elementos do índice início até fim-1. Se fim for omitido, vai até o final. Índices negativos contam do final. Exemplo:

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

let sliced = arr.slice(1, 3);
console.log(sliced); // [1, 2]
console.log(arr);    // [0, 1, 2, 3, 4] (inalterado)

// com índice negativo
let sliced2 = arr.slice(-2);
console.log(sliced2); // [3, 4]

splice(início, quantidadeRemove, item1, ..., itemN): Altera o array original removendo quantidadeRemove elementos a partir do índice início e opcionalmente adiciona novos itens. Retorna um array com os elementos removidos. Exemplo:

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

// remover 2 elementos a partir do índice 1
let removed = arr.splice(1, 2);
console.log(removed); // [1, 2]
console.log(arr);     // [0, 3, 4]

// remover 0 e adicionar 'a', 'b' no índice 2
arr = [0, 1, 2, 3, 4];
removed = arr.splice(2, 0, 'a', 'b');
console.log(removed); // []
console.log(arr);     // [0, 1, 'a', 'b', 2, 3, 4]

// substituir: remover 1 e adicionar 'x'
arr = [0, 1, 2, 3, 4];
removed = arr.splice(2, 1, 'x');
console.log(removed); // [2]
console.log(arr);     // [0, 1, 'x', 3, 4]

Diferença chave: slice não modifica o array original, é usado para cópia parcial; splice modifica o array, usado para adicionar/remover elementos. slice é imutável (cria novo array), splice é mutável.

indexOf/includes

Esses métodos são usados para buscar elementos em arrays. Ambos usam comparação estrita (===).

indexOf(elemento, índiceInicial): Retorna o primeiro índice onde o elemento é encontrado, ou -1 se não existir. O segundo parâmetro opcional indica a partir de qual índice começar a busca. Exemplo:

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

console.log(arr.indexOf(2));    // 1
console.log(arr.indexOf(2, 2)); // 3 (começa do índice 2)
console.log(arr.indexOf(5));    // -1

includes(elemento, índiceInicial): Retorna um booleano indicando se o elemento existe no array. Também aceita índice inicial. Exemplo:

let arr = [1, 2, 3];

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

// com índice inicial
console.log(arr.includes(1, 1)); // false (começa do índice 1)

Quando usar? Use includes quando você só precisa saber se o elemento existe, e indexOf quando precisa da posição. Ambos são O(n) no pior caso. Para arrays grandes, considere usar Set se precisar de buscas frequentes.

Observação sobre NaN: indexOf não encontra NaN (porque NaN !== NaN), mas includes sim (a partir do ES2016). Exemplo:

let arr = [NaN];
console.log(arr.indexOf(NaN)); // -1
console.log(arr.includes(NaN)); // true

Boas práticas finais

  • Prefira métodos imutáveis (como slice) quando possível, para evitar efeitos colaterais.
  • Use push e pop para pilhas; shift e unshift para filas (mas cuidado com performance).
  • Sempre verifique o retorno de indexOf contra -1 antes de usar o índice.
  • Para buscas por objetos, lembre-se que a comparação é por referência.

Referências

Exercícios

  1. Dado o array let arr = [10, 20, 30, 40];, use push para adicionar 50 ao final e depois pop para remover o último elemento. Qual o valor final de arr?

    ✓ Resposta: Após push(50), arr = [10,20,30,40,50]. Após pop(), arr = [10,20,30,40] (o mesmo que o original).
  2. Usando o array let frutas = ['maçã', 'banana', 'laranja'];, use unshift para adicionar 'uva' no início e depois shift para remover o primeiro elemento. Qual o resultado final?

    ✓ Resposta: Após unshift('uva'), frutas = ['uva', 'maçã', 'banana', 'laranja']. Após shift(), frutas = ['maçã', 'banana', 'laranja'] (original).
  3. Dado let numeros = [1, 2, 3, 4, 5];, use slice para obter um novo array com os dois últimos elementos (sem modificar o original). Escreva o código e o resultado.

    ✓ Resposta:
    let novo = numeros.slice(-2); // [4, 5]
    O array original permanece [1,2,3,4,5].
  4. Com o array let letras = ['a', 'b', 'c', 'd', 'e'];, use splice para remover 'c' e 'd' (2 elementos a partir do índice 2) e adicionar 'x' e 'y' no lugar. Qual o array resultante e quais elementos foram removidos?

    ✓ Resposta:
    let removidos = letras.splice(2, 2, 'x', 'y');
    console.log(letras);   // ['a', 'b', 'x', 'y', 'e']
    console.log(removidos); // ['c', 'd']
  5. Dado let dados = [1, 2, 3, 2, 1];, use indexOf para encontrar a posição da primeira ocorrência de 2 e includes para verificar se 5 existe. Escreva os resultados.

    ✓ Resposta:
    console.log(dados.indexOf(2)); // 1
    console.log(dados.includes(5)); // false