Debugar Javascript no browser

Debugue!

Antigamente a única forma que tínhamos de debugar um código Javascript no browser era usando alert(). Hoje os browsers mais modernos disponibilizam algumas ferramentas para ajudar nosso desenvolvimento. Uma delas é a API console.

Mas apesar de todos os seus métodos, nem sempre é possível resolver um problema de forma prática somente usando console.

Quais são então nossas outras opções? Vem comigo que eu te mostro ;)

A maior parte das ferramentas de desenvolvimento são bastante parecidas. Para os exemplos desse post, vou usar o Chrome DevTools, mas se você estiver usando Firefox, Opera ou qualquer outro navegador moderno, pode usar o Inspetor do seu próprio browser, que vai ser praticamente a mesma ideia :)

Source

Abrindo o DevTools, temos várias abas. Uma delas é a Sources:

Sources

Nessa aba, podemos ver todos os assets que foram carregados com a nossa página. Se você digitar Ctrl + P (ou Cmd + P no Mac), você consegue escolher um arquivo para abrir, com uma interface bem parecida com a do Sublime Text :)

Aba Source com busca de arquivos

Para facilitar a visualização do arquivo, você também pode esconder as abas laterais, clicando nos botões marcados:

Aba Source - botões para esconder abas

Tá, e no que isso vai me ajudar?

Calma jovem, vamos ver isso agora :D

Estrutura de arquivos

Vamos brincar um pouco. Crie uma estrutura de arquivos assim:

1
2
3
4
.
├── index.html
└── js
└── app.js

Na index.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test Debugger</title>
</head>
<body>
<form action="./" method="get" data-js="form">
<input type="text" name="name">
<button type="submit">Enviar</button>
</form>

<script src="js/app.js"></script>
</body>
</html>

Um simples formulário que envia um parâmetro name via GET. Perceba que, na aba Sources são mostrados todos os arquivos que são públicos do nosso projeto:

Formulário

Se você submeter esse formulário, ele vai fazer o que precisa ser feito: direcionar a ação para a mesma página (action="./") e passar via query string na URL o parâmetro do campo name com o valor preenchido:

Formulário enviado via GET

Até aqui, nada demais. Vamos agora escrever um pouco de JS para escutar o evento que faz o envio desse formulário. No arquivo js/app.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
;(function( doc, undefined ) {
'use strict';

function App() {
var $public = {};
var $private = {};

$public.init = function init() {
$private.initEvents();
};

$private.initEvents = function initEvents() {
doc.querySelector( '[data-js="form"]' )
.addEventListener( 'submit', $private.handleFormSubmit, false );
};

$private.handleFormSubmit = function handleFormSubmit() {
// do something
};

return $public;
}

doc.addEventListener( 'DOMContentLoaded', function() {
App().init();
}, false );
})( document );

Nada demais também até aqui. Simplesmente esperamos o DOM estar totalmente carregado e então iniciamos nossa função. Adicionamos um listener ao formulário para ouvir o evento submit. Antes do formulário ser enviado, a função de callback para o evento de submit ($private.handleFormSubmit) será executada.

Será?

Tente submeter o formulário. Como saber se entramos mesmo nessa função? Vamos adicionar um console.log:

1
2
3
$private.handleFormSubmit = function handleFormSubmit( e ) {
console.log( 'Enviou formulário' );
};

No seu console, marque a opção “Preserve log” para não apagar os logs se a página recarregar:

Console - Preserve log

Agora, submeta o formulário novamente. Se olharmos no console, a frase “Enviou formulário” será mostrada.

Tá, mas ainda eu não sei em que momento ele entrou nesse evento.

Certo, vamos então começar a debugar. Mudando a função de callback do submit, adicionando o comando debugger:

1
2
3
4
$private.handleFormSubmit = function handleFormSubmit( e ) {
debugger;
console.log( 'Enviou formulário' );
};

Recarregue a página e tente submeter o formulário novamente. O que aconteceu? O comando debugger não faz parte do Javascript. Ele é uma implementação dos browsers para criar um breakpoint na linha que tem o comando. Fazendo isso, você consegue literalmente parar a execução do browser naquele ponto:

Breakpoint com debugger

Para ver a imagem acima em tamanho real, abra-a em uma nova aba.

Se você reparar na aba lateral, onde mostra Scope Variables, ali você tem todas as variáveis locais e os seus respectivos valores. Ali ele mostra a variável e, representando o objeto Event, que é passada como parâmetro para a função handleFormSubmit pelo evento submit. Nesse objeto contém todas as informações relacionadas ao evento de submit do formulário.

Temos também o famoso this, que, nesse caso, é o nosso formulário. Se você pressionar F8 ou clicar na seta azul, ao lado da mensagem que aparece no topo Paused in debugger, o browser continua a execução do script até o próximo breakpoint. Como não temos mais nenhum, ele simplesmente executa as próximas ações normalmente, submetendo o formulário.

Legal, mas como eu posso tirar proveito disso?

Vou te mostrar algo bem legal agora. Vá no seu console, digite this e dê enter:

Console this window

O objeto this aponta para window, porque estamos no escopo global. Até aqui, nenhuma novidade. Agora, submeta o formulário para ele parar no debugger e faça a mesma coisa:

Console this form

Percebeu o que acabou de acontecer? Quando estamos parados em algum breakpoint, o escopo do console muda junto! Agora o this aponta para o nosso formulário!

Isso é bastante útil para debugar variáveis locais. Assim você consegue saber exatamente o valor que cada variável está recebendo naquele ponto exato do seu programa xD

Console this com valor do campo name

Que loko véi! Tem mais? :D

Tem sim xD

Você também pode criar seus próprios breakpoints diretamente na aba Sources, clicando no número da linha. Mas primeiro, remova a linha debugger do app.js. Agora crie seu breakpoint diretamente no browser:

Breakpoint manual

Coloquei o DevTools na lateral para facilitar a visualização. Criei dois breakpoints nas linhas 18 e 25, somente clicando sobre o número da linha. Na parte de baixo do DevTools (antes na lateral direita), temos uma guia chamada Breakpoints. Ali mostra todos os breakpoints que você adicionou no seu código. Clicando em cima de algum, o navegador dá o foco na linha com o breakpoint.

Agora, recarregue a tela.

Quando o DOM estiver pronto, o navegador para a execução na linha 25, onde fazemos o init do App. Clicando na seta azul ou pressionando F8, o navegador vai até o próximo breakpoint. Como só marcamos o breakpoint dentro do evento, então ele só vai parar quando submetermos o formulário.

Recarregue a tela novamente.

Perceba que, quando parados no breakpoint, ao lado da seta azul, temos uma outra seta, com uma bolinha embaixo. Clicando nela, ou pressionando F10, podemos ver qual o fluxo dentro do arquivo o navegador está seguindo, ou seja, quais são as próximas linhas que ele executa em ordem:

Próximo passo

Coloque um breakpoint na linha 2 e vá clicando nesse botão, e veja você mesmo o que acontece :)

Event Listener Breakpoints

Sabe quando você tem um código muito grande e bagunçado, e está tentando encontrar qual função de callback é chamada quando você clica em determinado elemento da tela? Você faz find no seu editor em busca da função, vasculha arquivos, e perde mó tempão pra conseguir achar. Na aba Sources, nós temos a guia Event Listener Breakpoints que pode nos ajudar a encontrar isso de forma mais fácil:

Source guia Event Listener Breakpoints

Abrindo essa guia, podemos ver vários eventos que podemos debugar. No caso do clique, você pode selecionar “Mouse > click”. Para exemplificar, vamos ver como podemos ver quando o DOM foi carregado. Abra a opção DOM Mutation e selecione DOMContentLoaded.

Recarregue a página.

Quando esse evento for executado, será mostrado qual (ou quais, se tiver mais de um) arquivo chama esse evento. Assim podemos ver exatamente, se estivermos usando alguma lib de terceiros, quem precisa esperar o DOM ser carregado, e o que essa lib carrega ao executar esse evento:

DOM Content Loaded

Essas são apenas algumas funcionalidades que você pode usar para debugar seu código Javascript. Experimente você mesmo as outras opções da aba Sources e veja o quanto isso te ajudará no dia a dia!

Até a próxima!

Sobre o #1postperday: https://blog.da2k.com.br/2014/12/31/um-post-por-dia/

Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: https://github.com/fdaciuk/fdaciuk.github.io/issues/1