Adicionar e remover elementos de um array em JS
push, pop, shift, unshift e splice mudam o array original mesmo declarado com const — e por que delete deixa buraco. Com toSpliced e with, do ES2023.
Para adicionar ou remover itens de um array, primeiro decida duas coisas: em
qual ponta você quer mexer e se o array original pode mudar. push e pop
atuam no fim; unshift e shift, no começo; splice, em uma posição que você
escolhe no meio.
Imagine uma fila escrita num quadro. push põe uma pessoa no fim, pop tira a
última, unshift coloca alguém na frente e shift chama a primeira. splice
permite apagar ou inserir a partir de uma posição específica. No JavaScript, o
“quadro” é o próprio array: esses cinco métodos alteram a lista original. Eles
não entregam uma cópia; devolvem o novo tamanho, o item removido ou a lista do
que saiu, dependendo do método.
Isso vale mesmo quando o array foi declarado com const. const impede trocar
a referência inteira, mas não congela os itens que estão dentro dela. Entender
essa diferença evita uma classe de bugs que aparece em parâmetros, estado de
componentes e objetos compartilhados.
Se você ainda não viu por que um array aceita mudar sendo const, a lição
arrays em JavaScript mostra o que o array
guarda por dentro. Aqui o assunto é o que você faz com ele.
push e pop: o fim do array
const carrinho = ['Teclado mecânico'];
const tamanho = carrinho.push('Mouse sem fio', 'Headset');
console.log(tamanho, carrinho);
const removido = carrinho.pop();
console.log(removido);
console.log(carrinho);push aceita quantos argumentos você quiser e devolve o novo tamanho — não
o array. Quem escreve const novo = lista.push(item) e depois trata novo como
lista está guardando o número 3.
pop devolve o item que saiu. Em array vazio, devolve undefined sem
reclamar.
shift e unshift: o começo do array
const fila = ['Pedido 1041', 'Pedido 1042', 'Pedido 1043'];
const proximo = fila.shift();
console.log(proximo);
console.log(fila);
fila.unshift('Pedido 1040 (urgente)');
console.log(fila);
console.log(fila.length);shift e unshift são o par simétrico de pop e push, do outro lado. A
simetria acaba no custo: mexer no começo obriga o motor a renumerar todos os
índices que vêm depois. Com uma fila de dez pedidos ninguém percebe; com
cem mil itens dentro de um laço, percebe.
splice: cortar e inserir no meio
splice(inicio, quantosRemover, ...itensParaInserir). É o único dos cinco que
faz as duas coisas de uma vez:
const carrinho = ['Teclado mecânico', 'Mouse sem fio', 'Headset', 'Webcam'];
const removidos = carrinho.splice(1, 2);
console.log(removidos);
console.log(carrinho);
carrinho.splice(1, 0, 'Monitor 27"', 'Suporte de monitor');
console.log(carrinho);
carrinho.splice(0, 1, 'Teclado sem fio');
console.log(carrinho);Três usos numa sequência só. Com quantosRemover em 0, splice vira uma
inserção pura. Com remoção e inserção juntas, vira substituição. E o valor de
retorno é sempre a lista do que saiu — array vazio quando nada saiu.
splice não é slice
Os nomes diferem por uma letra e os efeitos são opostos. Um corta o original, o outro fotografa:
const catalogo = ['Teclado mecânico', 'Mouse sem fio', 'Headset', 'Webcam'];
const paginaUm = catalogo.slice(1, 3);
console.log(paginaUm);
console.log(catalogo);
const cortados = catalogo.splice(1, 2);
console.log(cortados);
console.log(catalogo);As duas primeiras linhas: slice devolveu o pedaço e o catálogo continua com
quatro itens. As duas últimas: splice devolveu o mesmo pedaço e o catálogo
ficou com dois.
O retorno idêntico é o que torna a troca perigosa — você testa com o retorno,
vê o valor certo e só descobre o estrago quando outra parte do código lê o
catálogo. Vale também a diferença de assinatura: slice(inicio, fim) recebe
duas posições; splice(inicio, quantidade) recebe posição e contagem.
| método | o que devolve | altera o original | 2º argumento |
|---|---|---|---|
slice(i, f) |
pedaço novo | não | índice final (exclusivo) |
splice(i, n) |
o que foi removido | sim | quantidade a remover |
toSpliced(i, n) |
array novo já cortado | não | quantidade a remover |
const não impede push — impede reatribuir
Aqui está a prova, no mesmo arquivo:
const carrinho = ['Teclado mecânico'];
carrinho.push('Mouse sem fio');
carrinho.splice(0, 1);
console.log(carrinho);
carrinho = ['Headset'];O push passou. O splice passou. O console.log imprimiu o array já
modificado. Só a reatribuição quebrou.
const congela o vínculo entre o nome carrinho e aquele array específico.
O conteúdo do array não é da conta dele. É por isso que praticamente todo array
em código moderno é declarado com const — e continua mudando o dia inteiro. O
mesmo mecanismo, com objetos, aparece em
variáveis em JavaScript.
delete deixa buraco e não muda o length
delete funciona em objeto. Array é objeto. Logo, delete “funciona” em array
— e é justamente aí que a lógica te trai:
const carrinho = ['Teclado mecânico', 'Mouse sem fio', 'Headset'];
delete carrinho[1];
console.log(carrinho);
console.log(carrinho.length);
console.log(carrinho[1]);
console.log(carrinho.filter(Boolean).length);O item sumiu, o length continua 3 e a posição 1 virou um buraco — nem
undefined de verdade, uma chave que deixou de existir. O carrinho agora
mostra “3 itens” para o cliente e entrega dois. O filter(Boolean) no fim
prova que só duas posições sobreviveram.
Regra sem exceção prática: delete não remove item de array. Use splice
(quando quiser mutar) ou filter (quando quiser um array novo).
Sem mutar: toSpliced, with e toSorted
O ES2023 fechou o buraco mais irritante da API: até então, sort, reverse e
splice só existiam na versão que estraga o original. Agora existe o par
imutável de cada um:
const carrinho = ['Teclado mecânico', 'Mouse sem fio', 'Headset'];
const semMouse = carrinho.toSpliced(1, 1);
const trocado = carrinho.with(2, 'Headset Pro');
const ordenado = carrinho.toSorted();
console.log(semMouse);
console.log(trocado);
console.log(ordenado);
console.log(carrinho);Três operações e o carrinho da última linha continua exatamente como nasceu —
inclusive na ordem, que o toSorted reorganizou só na cópia. Trocar essa linha
por carrinho.sort() deixaria o original ordenado para sempre.
with(indice, valor) é a versão imutável de lista[i] = valor — e resolve num
método o que antes exigia espalhar e reatribuir.
Os pares completos são sort/toSorted, reverse/toReversed,
splice/toSpliced e a atribuição por índice, que ganhou with. Em React, em
Redux ou em qualquer estado que você compara por referência, é essa metade da
tabela que você quer.
Remover pelo conteúdo, não pela posição
No mundo real você raramente sabe o índice. Você sabe o SKU:
const carrinho = [
{ sku: 'TEC-001', nome: 'Teclado mecânico', preco: 289.9 },
{ sku: 'MOU-014', nome: 'Mouse sem fio', preco: 149.9 },
{ sku: 'HDS-007', nome: 'Headset', preco: 399 },
];
function removerPorSku(itens, sku) {
const posicao = itens.findIndex((item) => item.sku === sku);
if (posicao === -1) return false;
itens.splice(posicao, 1);
return true;
}
console.log(removerPorSku(carrinho, 'MOU-014'));
console.log(removerPorSku(carrinho, 'NAO-EXISTE'));
console.log(carrinho.map((item) => item.sku));A linha que faz esta função ser segura é if (posicao === -1) return false.
Sem ela, o código a seguir faria um estrago silencioso:
const carrinho = ['Teclado mecânico', 'Mouse sem fio', 'Headset'];
const posicao = carrinho.findIndex((item) => item === 'Webcam');
console.log(posicao);
carrinho.splice(posicao, 1);
console.log(carrinho);O produto procurado nem estava no carrinho, e mesmo assim um item foi
removido. Motivo: findIndex devolveu -1, e splice interpreta índice
negativo como contagem a partir do fim — -1 é a última posição. Nenhum erro,
nenhum aviso, o Headset sumiu.
Esse é o bug de array mais difícil de rastrear na produção, porque o sintoma
aparece na tela do cliente e não no log. Sempre teste o -1.
Esvaziar o carrinho inteiro
const carrinho = ['Teclado mecânico', 'Mouse sem fio', 'Headset'];
const espelho = carrinho;
carrinho.length = 0;
console.log(carrinho);
console.log(espelho);
console.log(carrinho === espelho);length = 0 esvazia no lugar: quem mais apontava para aquele array (aqui,
espelho) enxerga o array vazio junto. carrinho = [] faria o contrário —
criaria um array novo e deixaria espelho com os três itens antigos, o que
costuma virar uma tela que não atualiza.
splice(0, carrinho.length) tem o mesmo efeito de length = 0 e ainda devolve
o que saiu, se você precisar guardar.
Qual usar em cada situação
| o que você quer | método | muta |
|---|---|---|
| acrescentar no fim | push |
sim |
| tirar o último | pop |
sim |
| tirar o primeiro | shift |
sim |
| inserir no começo | unshift |
sim |
| remover/inserir no meio | splice |
sim |
| um pedaço, sem mexer | slice |
não |
| remover por condição | filter |
não |
| trocar um item por índice | with |
não |
| esvaziar mantendo a referência | length = 0 |
sim |
O critério de escolha não é “mutar é feio”. É: alguém mais está olhando para este array? Array local, criado três linhas acima e usado ali mesmo, pode mutar à vontade — é mais rápido e mais direto. Array que veio por parâmetro, que é estado de componente ou que está guardado num objeto compartilhado, você não muta: devolve um novo.
Faça um teste de dois minutos: crie const fila = ['Ana', 'Beto', 'Caio'],
guarde const copia = fila e execute fila.shift(). As duas variáveis devem
mostrar ['Beto', 'Caio'], porque apontam para o mesmo array. Repita usando
const novaFila = fila.slice(1) e confirme que o original não muda. Essa
comparação torna visível a diferença entre mutar e criar uma nova lista.
A próxima lição da trilha de JavaScript é percorrer array em JavaScript, e ela começa justamente com a armadilha de remover item enquanto você percorre. Depois vem map, filter e reduce, o lado imutável desta mesma história. O guia completo de JavaScript mostra onde cada assunto entra.
Perguntas frequentes
Se o array é const, por que push funciona?
Quando usar splice e quando usar slice?
Por que não devo usar delete num array?
toSpliced é sempre melhor que splice?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em Node 24.16.0, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- MDN — Array.prototype.splice() — developer.mozilla.org
- MDN — Array.prototype.toSpliced() — developer.mozilla.org
- ECMAScript 2026 Language Specification — Properties of the Array Prototype Object — tc39.es


