Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIniciantecódigo testado

window.location: redirecionar página com JavaScript

href, assign, replace e reload, mais URLSearchParams para ler a query string — com a URL real a cada passo e o laço de redirecionamento infinito reproduzido.

Rodolfo Mori6 min de leitura

window.location é o objeto que representa a URL da página. Ele location.pathname, location.search — e escreve: atribuir algo a location.href manda o navegador para outro endereço.

js
window.location.href = '/checkout';

Como window é o objeto global no navegador, location.href sem o window. na frente é a mesma coisa. E existem três formas de sair da página que parecem iguais e não são: href, assign e replace — a última é a única que não deixa rastro no histórico. Os exemplos abaixo são de uma loja rodando em loja.club.

A URL é endereço; o histórico é o caminho percorrido

Pense no navegador como um motorista. window.location é o cartão com o endereço atual: domínio, caminho, busca e fragmento. Alterar href ou chamar assign() manda o motorista para outro lugar e registra a viagem. replace() troca o cartão atual sem guardar aquele trecho no caminho de volta.

O nome técnico é objeto Location, uma interface do navegador sobre a URL da página. Ele não é a ferramenta certa para todo link: um endereço que o usuário pode escolher deve continuar sendo <a href>. Faça um teste num arquivo local ou ambiente descartável: navegue com assign, volte, depois repita com replace. O botão voltar conta a diferença melhor que a assinatura dos métodos — um acrescenta uma entrada ao histórico; o outro substitui a atual.

As partes da URL

Estando em https://loja.club/produtos/teclado-mecanico?cor=preto&frete=sedex#avaliacoes:

js
console.log('href    :', location.href);
console.log('origin  :', location.origin);
console.log('protocol:', location.protocol);
console.log('host    :', location.host);
console.log('hostname:', location.hostname);
console.log('port    :', JSON.stringify(location.port));
console.log('pathname:', location.pathname);
console.log('search  :', location.search);
console.log('hash    :', location.hash);
href : https://loja.club/produtos/teclado-mecanico?cor=preto&frete=sedex#avaliacoes origin : https://loja.club protocol: https: host : loja.club hostname: loja.club port : "" pathname: /produtos/teclado-mecanico search : ?cor=preto&frete=sedex hash : #avaliacoes

Três detalhes que economizam meia hora de depuração: protocol vem com os dois pontos ("https:", não "https"), port é string vazia quando é a porta padrão (443 ou 80) e search traz o ? junto. host inclui a porta quando ela existe; hostname nunca inclui.

href, assign e replace

js
location.href = '/checkout';   // navega e empilha no histórico
location.assign('/pagamento'); // idêntico ao anterior
location.replace('/pedido/4412'); // navega e SUBSTITUI a entrada atual

Acompanhando a URL a cada passo:

inicial https://loja.club/carrinho href = https://loja.club/checkout assign() https://loja.club/pagamento replace() https://loja.club/pedido/4412

A diferença não aparece na URL: aparece no botão “voltar”. Com href ou assign, voltar leva à página anterior. Com replace, a entrada atual é sobrescrita e o voltar pula direto para a de antes dela.

forma empilha no histórico usar quando
location.href = url sim navegação normal, disparada pelo usuário
location.assign(url) sim igual a href, com cara de método
location.replace(url) não pós-login, pós-logout, redirecionar quem não pode estar ali
location.reload() recarrega a mesma depois de uma ação que mudou o servidor

A regra é essa: redirecionamento automático usa replace. Se você mandar quem não está logado para /login com href, o botão voltar devolve a pessoa para a página protegida, que redireciona de novo — e ela fica presa.

Ler a query string com URLSearchParams

Fatiar location.search com split('&') funciona até aparecer o primeiro acento, o primeiro + ou o primeiro parâmetro repetido. URLSearchParams já resolve os três:

js
// estamos em /busca?q=teclado+mec%C3%A2nico&marca=redragon&marca=logitech&pagina=2
const params = new URLSearchParams(location.search);

console.log('q      :', params.get('q'));
console.log('pagina :', params.get('pagina'), typeof params.get('pagina'));
console.log('marca  :', params.getAll('marca'));
console.log('cupom  :', params.get('cupom'));
console.log('tem cupom?', params.has('cupom'));

for (const [chave, valor] of params) console.log('  ', chave, '=', valor);
q : teclado mecânico pagina : 2 string marca : [ 'redragon', 'logitech' ] cupom : null tem cupom? false q = teclado mecânico marca = redragon marca = logitech pagina = 2

O + virou espaço e o %C3%A2 virou â sem você pedir. get devolve null quando o parâmetro não existe — e pagina é string, como tudo que vem de URL: converta com Number() antes de usar em conta, do mesmo jeito que o valor de um input.

Montar URL nova sem concatenar string

Escrever '/busca?q=' + termo funciona até o termo ter um &, um espaço ou um acento. URL mais searchParams codifica sozinho:

js
const destino = new URL('/busca', location.origin);

destino.searchParams.set('q', 'teclado mecânico');
destino.searchParams.set('ordem', 'menor-preco');
destino.searchParams.set('marca', 'Redragon & Cia');

console.log(destino.href);
https://loja.club/busca?q=teclado+mec%C3%A2nico&ordem=menor-preco&marca=Redragon+%26+Cia

O & do nome da marca saiu como %26 e não quebrou a query. set substitui um parâmetro existente; append adiciona outro com o mesmo nome; delete remove.

Quando a mudança é só de filtro e você não quer recarregar a página, troque o location por history.replaceState:

js
const url = new URL(location.href);
url.searchParams.set('ordem', 'menor-preco');
url.searchParams.set('pagina', '2');

history.replaceState(null, '', url);
console.log('URL depois do replaceState:', location.href);
URL depois do replaceState: https://loja.club/busca?q=teclado&ordem=menor-preco&pagina=2

A barra de endereço mudou, o conteúdo não recarregou, e o usuário pode copiar o link com os filtros aplicados. É como todo catálogo sério faz filtro.

window, document e navigator

Os três aparecem juntos e fazem coisas diferentes:

objeto é exemplos
window a aba: o objeto global do navegador location, localStorage, setTimeout, innerWidth
document o conteúdo carregado nessa aba querySelector, title, body, cookie
navigator o programa e o dispositivo language, onLine, clipboard, geolocation
js
console.log('window.location === document.location ?', window.location === document.location);
console.log('document.URL  :', document.URL);
console.log('location.href :', location.href);
window.location === document.location ? true document.URL : https://loja.club/carrinho location.href : https://loja.club/carrinho

document.location e window.location são o mesmo objeto — a diferença é que document.URL é só leitura, enquanto location.href também escreve. Nada disso existe no Node: lá não há aba, não há documento e não há usuário.

Erros comuns

O laço de redirecionamento infinito

Uma guarda de autenticação, colocada num script que roda em toda página:

js
// roda em todas as páginas do site
if (localStorage.getItem('token') === null) {
  location.href = '/login';
}

Simulando o carregamento de cinco páginas seguidas:

carregou /carrinho -> redireciona para /login carregou /login -> redireciona para /login carregou /login -> redireciona para /login carregou /login -> redireciona para /login carregou /login -> redireciona para /login

A página /login também roda o script, também não encontra token, e também redireciona — para ela mesma. O Chrome corta com “Throttling navigation to prevent the browser from hanging”; o Firefox mostra “A página não está redirecionando corretamente”. Nenhum dos dois aponta a linha culpada.

A correção é a condição que faltava: não redirecione se você já está no destino.

js
if (localStorage.getItem('token') === null && location.pathname !== '/login') {
  location.replace('/login');
}
carregou /carrinho -> redireciona para /login carregou /login -> segue carregou /login -> segue carregou /login -> segue carregou /login -> segue

Repare que a correção trocou href por replace: além de parar o laço, ela impede que o botão voltar jogue a pessoa de novo na página protegida.

new URL sem base

js
const destino = new URL('/checkout');
destino.searchParams.set('cupom', 'FRETE10');
node:internal/url:840 href = bindingUrl.parse(input, base, true); ^

TypeError: Invalid URL at new URL (node:internal/url:840:25) at file:///private/tmp/loja/redirecionar.mjs:4:17 { code: ‘ERR_INVALID_URL’, input: ‘/checkout’ }

Node.js v24.16.0

O construtor URL exige uma URL absoluta, ou um caminho mais uma base. O input: '/checkout' no fim da mensagem entrega o culpado. A correção é new URL('/checkout', location.origin) — e é por isso que o exemplo de montar URL, mais acima, passa o origin como segundo argumento.

O typo que some no meio do redirecionamento

js
localStorage.removeItem('token');
window.locaton.href = '/login';
file:///private/tmp/loja/sair.mjs:5 window.locaton.href = '/login'; ^

TypeError: Cannot set properties of undefined (setting ‘href’) at file:///private/tmp/loja/sair.mjs:5:21 at ModuleJob.run (node:internal/modules/esm/module_job:439:25)

Node.js v24.16.0

window.locaton é undefined porque acessar propriedade inexistente de um objeto não dá erro — dá undefined. O erro só acontece na etapa seguinte, ao tentar escrever href nele. O sintoma pelo qual você chega aqui é cruel: o token foi apagado e o usuário continuou na página, agora deslogado sem saber.

Quando redirecionar no JavaScript — e quando não

Redirecionamento em JavaScript é o último recurso. Ele acontece depois de a página carregar, o que significa página em branco piscando, gasto de banda e um buraco para quem usa leitor de tela.

  • Mudança permanente de endereço? É 301 no servidor, não location.href. Buscador entende redirecionamento HTTP; JavaScript ele interpreta com atraso e desconfiança.
  • Link para outra página? É <a href>. Um <div onclick="location.href=..."> não abre em nova aba, não mostra o destino na barra de status e não é focável pelo teclado.
  • Depois de uma ação que o usuário disparou — pagou, saiu, salvou: aí sim, location.replace() para o destino.
  • Precisa da URL como estado da tela? history.replaceState, não navegação.

Esta é a última lição do bloco de eventos e navegador da trilha de JavaScript. Com addEventListener, formulário validado, localStorage e location, você já tem o que uma página precisa para reagir ao usuário sem framework nenhum. O guia completo de JavaScript mostra o que vem depois.

  • location
  • redirecionamento
  • url
  • urlsearchparams
  • navegador

Perguntas frequentes

Qual a diferença entre location.href e location.replace?
href e assign empilham a página nova no histórico, então o botão voltar leva de volta à anterior. replace troca a entrada atual, e o voltar pula para a página de antes — é o que você quer depois de um login ou logout.
Por que location.search vem com o ponto de interrogação?
Porque search é a string bruta da URL, incluindo o separador. Você raramente trabalha com ela na mão: passe direto para URLSearchParams, que aceita a string com ou sem o ponto de interrogação e cuida do resto.
Dá para mudar a URL sem recarregar a página?
Dá, com history.pushState ou history.replaceState. É assim que um filtro de catálogo deixa a URL compartilhável sem recarregar nada. Mexer em location, ao contrário, sempre dispara uma navegação de verdade.
Posso confiar no valor que vem da query string?
Nunca. Qualquer pessoa edita a barra de endereço. Trate parâmetro como entrada de usuário: valide o formato, converta o tipo e jamais coloque o conteúdo cru no innerHTML — é entrada clássica de XSS.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

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

  1. MDN — Location — developer.mozilla.org
  2. MDN — URLSearchParams — developer.mozilla.org
  3. URL Standard — URLSearchParams class — url.spec.whatwg.org

Continue por aqui