Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Debugging avanzato con Javascript

Usare i debugger come Firebug per scovare e correggere i bug presenti nel codice Javascript
Usare i debugger come Firebug per scovare e correggere i bug presenti nel codice Javascript
Link copiato negli appunti

Questa è la traduzione dell'articolo Advanced Debugging with JavaScript di Chris Mills e Hallvord R. M. Steen pubblicato originariamente su A List Apart il 03 Febbraio 2009. La traduzione viene qui presentata con il consenso dell'editore e dell'autore.

Se usati bene i debugger Javascript possono aiutarvi a trovare e risolvere gli errori presenti nel codice. Per diventare esperti in questo tipo di operazione dovrete conoscere gli strumenti per il debug che avete a disposizione, il flusso di lavoro tipico nell'attività di debugging e i requisiti di codice per un debug efficace. In questo articolo discuteremo alcune tecniche avanzate per diagnosticare e risolvere i bug usando un'applicazione web di esempio.

Una nota sull'accessibilità

L'articolo mette in evidenza i punti di forza e le differenze tra i principali strumenti di debug e mostra come eseguire compiti di debug avanzato su Javascript. I nostri metodi sono spesso basati sull'uso del mouse; se preferite la tastiera o se usate tecnologie assistive come gli screen reader per interagire con questi strumenti, dovreste consultare la loro documentazione per capire come e se questi tool possono funzionare per voi.

I debugger

Con un numero crescente di buoni debugger disponibili, il programmatore Javascript può guadagnare molto imparando ad usarli bene. Le interfacce dei debugger Javascript stanno diventando più pulite, più standardizzate tra i vari prodotti e più facili da usare: ciò rende più semplice per i novizi e per gli utenti più esperti imparare le tecniche di debugging.

Al momento ci sono strumenti di debug disponibili per i principali browser:

Al momento Firebug e Dragonfly sono le opzioni più stabili. La versione beta di IE8 a volte ignora i breakpoint e al momento in cui scriviamo questo articolo, il WebInspector sembrava avere delle incompatibilità con le nightly build di Webkit.

Familiarizzate con più strumenti di debug, perché non saprete mai in quale browser si verificherà il prossimo errore. Dal momento, poi, che i vari tool sono tutto sommato comparabili per le funzionalità che offrono, è facile passare da uno all'altro una volta che si sappia come usarne uno.

Il flusso di lavoro del debug

Quando si investiga su un problema specifico, seguirete in genere questo procedimento:

  1. Trovate il codice che vi interessa nel pannello per la vista del codice del debugger
  2. Impostate uno o più breakpoint dove pensate che possano accadere cose interessanti
  3. Eseguite lo script ricaricando la pagina nel caso di script inline o cliccando su un pulsante in caso lo script sia attivato da un gestore di eventi
  4. Aspettate fin quando il debugger mette in pausa l'esecuzione rendendo possibile procedere nel codice passo a passo
  5. Investigate i valori delle variabili. Per esempio, cercate le variabili che non sono definite quando invece dovrebbero contenere un valore o quelle che restituiscono "false" quando vi aspettate invece che restituiscano "true"
  6. Se necessario usate la linea di comando per valutare il codice o modificare la variabile per fare dei test
  7. Trovate il problema imparando quale pezzo di codice o quale input hanno causato le condizioni di errore

Per creare un breakpoint, potete anche aggiungere questa dichiarazione per il debug al codice:

function frmSubmit(event){
    event = event || window.event;
    debugger;
    var form = this;
}

Requisiti per l'uso dei debugger

La maggior parte dei debugger richiede codice ben formattato. Gli script scritti su una sola riga rendono difficile la scoperta di errori nei debugger basati sulla lettura riga per riga del codice. Il codice offuscato può anch'esso essere difficile da debuggare, specialmente il codice che è stato compresso (packed) e ha bisogno di essere di espanso usando eval (). Molte librerie Javascript vi consentono di scegliere tra versioni compresse/offuscate e ben formattate: queste versioni non compresse, seppure più 'pesanti' sono quelle idealmente da usare per il debug perché hanno codice ben formattato.

Una dimostrazione di debug

Iniziamo con un piccolo esempio, riempito appositamente di bug, per imparare a diagnosticare e trattare i problemi nel codice Javascript. Il nostro esempio è rappresentato dalla schermata di login di un'applicazione web.

Immaginate di essere al lavoro su questa favolosa applicazione e che i vostri tester vi chiedano di investigare su questa lista di bug:

  1. Il messaggio "Loading..." sulla barra di stato non scompare quando l'applicazione è completamente caricata
  2. La lingua di default è il norvegese anche sulle versioni in inglese di Firefox e IE
  3. Una variabile globale chiamata prop viene creata da qualche parte
  4. Nel DOM viewer tutti gli elementi hanno un attributo "clone"
  5. La validazione dei form rispetto alla lunghezza minima del contenuto inserito nei campi non funziona: inviando il form con uno username di un solo carattere dovrebbe essere generato e visualizzato un messaggio di errore
  6. È possibile lasciare vuoto il campo della password: al momento di inviare il form, invece, dovrebbe comparire un messaggio che avvisa dell'impossibilità di lasciare quel campo non compilato
  7. Il login non funziona e viene mostrato un messaggio di errore che parla di un attacco di tipo cross-site scripting individuato

Lanciare i debugger

In Firefox dovrete essere sicuri di aver installato l'estensione Firebug. Per iniziare selezionate dal menu Tools (Strumenti) > Firebug > Open Firebug (Apri Firebug) per iniziare.

Su Opera 9.5 e successivi, scegliete dal menu Tools (Strumenti) > Advanced (Avanzate) > Developer Tools (Strumenti per gli sviluppatori).

Su IE8 selezionate Tools > Developer Tools.

Su Safari o WebKit, prima abilitate il menu di debug se non è abilitato, poi selezionate Debug (Sviluppo) > Show Web Inspector (Mostra...).

È il momento di accendere i debugger. Per seguire la demo, prestate attenzione alle istruzioni passo per passo che offriremo. Dal momento che alcune istruzioni richiedono modifiche sul codice, potete salvare la pagina della demo in locale e caricarla dal vostro disco prima di iniziare.

Bug 1: il messaggio "Loading..." sulla barra di stato

Se date un'occhiata alle applicazioni di debug in Firebug e Dragonfly, vi troverete inizialmente davanti a queste schermate (attivate in entrambi i casi la tab 'Scripts'):

Figura 1 - Schermate di Dragonfly e Firebug
screenshot
screenshot

Scorrendo il codice sorgente nel debugger, notate che c'è una funzione clearLoadingMessage() definita all'inizio del codice stesso. Sembra essere un buon punto per impostare un breakpoint.

Ecco come fare:

  1. Cliccate sul numero di riga alla sinistra per impostare un breakpoint in corrispondenza della prima riga all'interno della funzione clearLoadingMessage()
  2. Ricaricate la pagina

Nota: il breakpoint deve essere impostato su una riga con codice che sarà eseguito quando la funzione viene attivata. La riga che contiene la funzione clearLoadingMessage() { è solo l'intestazione della funzione. Impostando un breakpoint in quel punto non farà andare in pausa il debugger. Impostate il breakpoint, invece, sulla prima riga all'interno della funzione.

Quando la pagina viene ricaricata, l'esecuzione dello script si blocca in corrispondenza del breakpoint e vedrete qualcosa come quello mostrato in figura 2 (Dragonfly è in alto, Firebug in basso):

Figura 2 - Impostazione del breakpoint in Dragonfly e Firebug
screenshot

Procediamo passo per passo all'interno della funzione. Vedrete che essa aggiorna i due elementi DOM e che su una riga immediatamente successiva a quella dove abbiamo impostato il breakpoint è presente la parola statusbar. Sembra importante. È probabile che getElements( 'p', {'class':'statusbar'} )[0] trovi l'elemento statusbar nel DOM. C'è un modo per testare questa supposizione rapidamente?

Incollate lo snippet di codice che vi interessa nella linea di comando per verificare. La figura 3 mostra tre screenshot (nell'ordine Dragonfly, Firebug e IE8) dopo la lettura di innerHTML o outerHTML dell'elemento restituito dal comando su cui state investigando:

Figura 3 - Output restituito da Dragonfly, Firebug e IE8
screenshot

Procediamo così nel test:

  1. Trovate la linea di comando:
    Su Firebug selezionate la tab "Console"
    Su Dragonfly cercate sotto il pannello con il codice sorgente Javascript
    Nei Developer Tools di IE8 trovate la tab sulla destra con l'etichetta "Console"
  2. Incollate getElements( 'p', {'class':'statusbar'} )[0].innerHTML nel pannello della linea di comando
  3. Premete Invio

La linea di comando è uno strumento molto utile che consente di testare piccoli snippet di codice rapidamente. L'integrazione della console di Firebug è anche molto utile dal canto suo: se il vostro comando restituisce come output un oggetto, avrete a disposizione una vista molto intelligente del tutto. Per esempio, otterrete una rappresentazione in forma simile a quella del markup se si tratta di un oggetto DOM.

Potete usare la linea di comando per esplorare il problema più in profondità. La riga di Javascript che stiamo cercando fa le seguenti tre cose:

  1. Cattura un riferimento all'elemento usato nella pagina come barra di stato. Nella vista offerta dal DOM Inspector, vedrete che il markup che corrisponde a questo elemento è <p class="statusbar">
  2. Cerca poi il suo firstChild, in altre parole, il primo nodo all'interno del paragrafo
  3. Imposta la proprietà innerText

Proviamo a eseguire qualcosa di più del comando dalla linea di comando. Per esempio, potreste chiedervi qual è il valore corrente della proprietà innerText di questo elemento prima che sia impostato. Per verificare potete inserire questo intero comando nella console:

getElements( 'p', {'class':'statusbar'} )[0].firstChild.innerText

Sorprendentemente, l'output non restituisce... nulla. Così l'espressione getElements( 'p', {'class':'statusbar'} )[0].firstChild punta a qualcosa nel DOM che non contiene testo, o che non ha una proprietà innerText.

Dunque, la prossima domanda è: qual è esattamente il primo nodo figlio del paragrafo? Chiediamo alla linea di comando (osservate i risultati nell'immagine qui sotto) inserendo :

getElements( 'p', {'class':'statusbar'} )[0].firstChild
Figura 4 - Output del debugger di Dragonfly [object-text]
screenshot

L'output di Dragonfly [object Text] mostra che questo è un nodo di testo DOM. Firebug ci mostra il contenuto del nodo di testo come un link al DOM inspector. Avete ora trovato il problema che causa il primo bug: un nodo di testo non ha una proprietà innerText, solo nodi di elemento ce l'hanno. Dunque, impostando p.firstChild.innerText non produce nulla. Questo bug può essere risolto sostituendo innerText con nodeValue, che è una proprietà del W3C DOM con cui si definiscono i nodi di testo.

Avete la possibilità ora di rivedere l'esempio:

  1. Premete F5 o premete il pulsante 'run' per terminare lo script, ora che avete trovato il problema
  2. Ricordate di eliminare i vecchi breakpoint cliccando di nuovo sul numero di riga

Termina qui la prima parte dell'articolo. Vedremo la settimana prossima come affrontare gli altri bug.

Bug 2: problemi nell'individuazione della lingua

Avrete notato nel codice la riga con var lang; /*language*/ più o meno in cima alla parte Javascript del codice. Il codice che imposta questa variabile è probabilmente responsabile del secondo bug. Potete trovare le cose nel codice rapidamente usando la comoda funzionalità di ricerca fornita da entrambi i debugger. In Dragonfly è proprio sopra il pannello di vista del codice; in Firebug si trova in alto, a destra (figura 5):

Figura 5 - Ricerca in Firebug (sopra) e Safari (sotto)
screenshot

Per trovare il punto che ha a che fare con la localizzazione dell'applicazione:

  1. Scrivete lang = nel campo di ricerca
  2. Impostate un breakpoint sulla riga in cui alla variabile lang è assegnato un valore
  3. Ricaricate la pagina

Il WebInspector di Safari offre anche una potente funzionalità di ricerca. WebInspector vi consente di cercare in tutto il codice nello stesso tempo, compreso il markup, i CSS e Javascript. Il risultato viene mostrato in un pannello dedicato dovete fare doppio click sui risultati per saltare alla riga corrispondente, come mostrato nello screenshot.

Per capire cosa fa questa funzione:

  1. Usate il pulsante "step into" (su Firebug è una freccia con la punta rivolta verso il basso, n.d.t) per entrare nella funzione getLanguage
  2. Cliccate ancora ripetutamente sul pulsante "step into" per procedere nel codice una riga alla volta
  3. Date un'occhiata all'overview delle variabili locali per vedere come cambiano mentre si procede passo a passo in questa funzione

Procedendo nel contesto della funzione getLanguage, vedrete che prova a leggere il valore per la lingua dalla stringa dello user agent. L'autore di questo codice ha notato che nel contesto di questa stringa sono incluse, in certi browser, alcune informazioni sulla lingua e pertanto cerca di parsare navigator.userAgent per estrarre questa informazione:

var str1 = navigator.userAgent.match( /((.*))/ )[1];
var ar1 = str1.split(/s*;s*/), lang;
for (var i = 0; i < ar1.length; i++){
    if (ar1[i].match(/^(.{2})$/)){
        lang = ar1[i];
    }
}

Procedendo all'interno di questo codice con i debugger, potete usare l'overview delle variabili locali. La figura 6 mostra Firebug e i Developer Tools di IE8 con l'array ar1 espanso per visualizzare gli elementi al suo interno:

Figura 6 - Pannello delle variabili locali su Firebug (sinistra) e IE8 (destra)
screenshot

La dichiarazione ar1[i].match(/^(.{2})$/) cerca una stringa che è lunga due caratteri, aspettando di trovare un codice per la lingua di due caratteri come en o no. Tuttavia, come potete vedere dagli screenshots, l'informazione sulla lingua nella stringa dello user agent di Firefox è al momento nn-NO. IE non ha informazioni sulla lingua in questa parte della stringa dello user agent.

Abbiamo trovato il secondo bug. La funzione per individuare la lingua cerca un codice di due lettere, ma Firefox ha una stringa con 5 caratteri e IE non presenta nessuna informazione. Il codice per individuare la lingua dovrebbe essere probabilmente parsato diversamente e sostituito con codice lato server che usi l'header HTTP Accept-Language o che vada a leggere navigator.language. Oppure navigator.userLanguage su IE. Un esempio di come potrebbe apparire questa funzione è questo:

function getLanguage() {
    var lang;

    if (navigator.language) {
        lang = navigator.language;
    } else if (navigator.userLanguage) {
        lang = navigator.userLanguage;
    }

    if (lang && lang.length > 2) {
        lang = lang.substring(0, 2);
    }

    return lang;
}

Bug 3: la misteriosa variabile prop

Nella figura 7 potete vedere chiaramente la misteriosa variabile prop:

Figura 7 - Pannello delle variabii locali su Firebug (sopra) e Dragonfly (sotto) che mostrano la variabile prop
screenshot

Le applicazioni scritte bene mantengono al minimo il numero di variabili globali perché esse possono causare confusione quando differenti sezioni dell'applicazione provano a usare lo stesso nome di variabile. Immaginate che domani un altro team di sviluppatori aggiunga una nuova funzionalità alla nostra applicazione e nomini una variabile come prop. Avremmo due parti dell'applicazione che provano a usare lo stesso nome di variabile per fare cose differenti. Questa pratica può essere l'origine per conflitti e bug. Dunque, dobbiamo verificare dove è impostata questa variabile e vedere se c'è un modo per renderla locale. Potete iniziare facendo una ricerca come abbiamo fatto per il bug 2, ma forse c'è un modo più intelligente...

I debugger per molti altri linguaggi di programmazione adottano il concetto di "watch" che può interrompere il debugger quando una variabile cambia. Né Dragonfly né Firebug supportano il "watch", ma è facile ottenere lo stesso effetto aggiungendo la seguente riga di codice di debug all'inizio del codice dello script che ci sta dando problemi:

__defineSetter__('prop', function() { debugger; });

Per aggiungere questa funzionalità che emula il "watch" allo script:

  1. Aggiungete il codice di debug all'inizio del primo script
  2. Ricaricate la pagina
  3. Notate come si interrompe quando si incontra un problema

Usando getters e setters possiamo quindi emulare la funzionalità "watch" e si possono definire dei breakpoint intelligenti.

I Developer Tools di IE8 hanno un pannello "watch", ma non è possibile interrompere l'esecuzione quando una variabile viene modificata. Considerato il supporto incompleto di IE8 per getters e setters, non è possibile emulare la funzionalità nel modo in cui è possibile fare con Opera, Firefox e Safari.

Quando ricaricate l'applicazione, essa si interrompe immediatamente nel punto in cui la variabile globale prop è stata definita. Di fatto si ferma alla riga del codice di debug che avete aggiunto perché è lì che si trova la dichiarazione debugger. Un click sul pulsante "step out" vi porterà dalla funzione setter al punto in cui la variabile è impostata. Questo codice si trova all'interno della funzione getElements:

for (prop in attributes) {
    if (el.getAttribute(prop) != attributes[prop]) includeThisElement»
= false;

Ora si ferma proprio sotto la linea che inizia con for (prop. Qui potete vedere che la variabile prop è usata senza essere definita come variabile locale, con una keyword var all'interno della funzione. Basta cambiare tutto in for (var prop per fissare il bug 3.

Bug 4: l'attributo clone che non dovrebbe essere lì

Il quarto bug è stato riscontrato da un tester che usava il DOM Inspector. Non è infatti visibile partendo dall'interfaccia utente dell'applicazione. Non appena, però, si apre il DOM Inspector (in Firebug c'è la tab "HTML", mentre in Dragonfly la funzionalità è chiamata "DOM") diviene chiaro che molti elementi hanno attributi clone con al loro interno del codice Javascript che non dovrebbe essere lì:

Figura 8 - Il DOM inspector di Dragonfly mostra il codice problematico
screenshot

Ogni elemento creato dallo script ha un attributo clone superfluo. Dato che è qualcosa che l'utente finale non noterà mai potrebbe sembrare un bug non troppo serio. Ma immaginate l'impatto sulle performance se questo script venisse usato per creare un albero DOM con centinaia o migliaia di elementi...

Il modo più rapido per trovare questo problema consiste nel definire un breakpoint (interruzione) che si verifichi solo quando un attributo chiamato clone è impostato su un elemento HTML. I debugger possono fare questo?

Javascript è un linguaggio molto flessibile e uno dei suoi punti di forza (o di debolezza, dipende dai punti di vista) è che si possono sostituire funzioni core con quelle create da noi. Aggiungete questo snippet di codice di debug alla pagina e sostituirà l'originale metodo setAttribute () con uno che interrompe se viene impostato un attributo clone:

var funcSetAttr = Element.prototype.setAttribute; /* keep a pointer
 to the original function */

Element.prototype.setAttribute = function(name, value) {
    if (name == 'clone') {
        debugger; /* break if script sets the 'clone' attribute */
    }
    funcSetAttr.call(this,name,value);  /* call original function to
    ensure those other attributes are set correctly */
};

Per scoprire il punto di creazione dell'attributo clone:

  1. Aggiungete il codice di debug all'inizio del primo script del documento
  2. Ricaricate la pagina

Appena ricaricate la pagina, lo script inizia a generare il DOM, ma si interrompe la prima volta in cui tenta di impostare il cattivo attributo clone.

Nota: nelle versioni correnti di Firefox setAttribute ha varie implementazioni specifiche per elemento. Il codice visto qui sopra funziona come ci si attende su Opera; per ottenere lo stesso effetto su Firefox potere sostituire la parola Element con HTMLFormElement per rimpiazzare il più specifico metodo HTMLFormElement.prototype.setAttribute.

Quando l'esecuzione si interrompe al breakpoint, vorrete sapere dove si è verificata la chiamata a setAttribute(). Ciò significa che dovete tornare indietro alla lista delle funzioni richiamate e scoprire come lo script è arrivato a quel punto. Per questo scopo usiamo la funzionalità stack.

La figura 9 mostra gli stack delle chiamate in Dragonfly e IE8 quando si stoppano in corrispondenza dei breakpoint. Giusto come riferimento, ho creato un breakpoint manuale su IE8 più o meno nella stessa posizione in cui si ferma la tecnica del setAttribute(). Potete vedere che in Dragonfly la funzione richiamata più di recente è messa all'inizio (è la funzione anonima che è stata mappata su setAttribute()). È stata richiamata da makeElement alla riga 95:

Figura 9 - Gli stack delle chiamate di Dragonfly e IE8
screenshot

La figura 10 mostra invece la vista degli stack su Firebug. La riga setAttribute < makeElement < init vicina al nome del file è lo stack (potete vedere che la funzione richiamata più di recente è quella all'estrema sinistra):

Figura 10 - Gli stack delle chiamate su Firebug
screenshot

Cliccando le funzioni precedenti nella lista degli stack potete tornare indietro a ritroso attraverso le chiamate e osservare come siete arrivati a quel punto. È importante che proviate da voi per comprendere pienamente quanto è potente questa funzionalità. Notate che quando passate ad un'altra voce di stack il pannello delle variabili locali è aggiornato per mostrarvi lo stato corrente delle variabili nella funzione che effettua la chiamata.

Come usare lo stack delle chiamate per trovare una funzione problematica:

  1. Cliccate la funzione che volete vedere nello stack delle chiamate
  2. Notate che il pannello delle variabili locali viene aggiornato per mostrare le variabili locali per quella funzione
  3. Ricordate che se usate i pulsanti di step essi vi porteranno avanti dall'ultima chiamata anche se state ispezionando altre parti dello stack

Cliccando il riferimento a makeElement veniamo portati indietro a questa parte:

for (var prop in attributes) {
    el.setAttribute(prop, attributes[prop]);
}

dove vedete la chiamata a setAttribute. I pannelli per le variabili locali mostrano che il valore di prop è in effetti clone. La variabile prop è definita nel loop for...in. Ciò ci dice che una delle proprietà dell'oggetto attributes deve essere chiamata clone.

La variabile attributes è definita come secondo argomento della funzione. Se andate un passo sopra alla parte init dello stack, potete vedere la precedente chiamata di funzione è stata questa:

var form = makeElement(‘form’, { action:’/login’,
method:’post’, name:’loginform’ }, document.body);

Il secondo argomento per il metodo è evidenziato in grassetto: questo oggetto non ha una proprietà clone. Dunque, da dove viene?

Se cliccate sulla funzione makeElement nello stack potete ispezionare la variabile attributes. In Firebug vedrete apparire la proprietà clone. Potete cliccare la funzione a cui fa riferimento per saltare alla definizione (notate la riga evidenziata in blu nella figura 11):

Figura 11 - Firebug ci mostra dove è stata definita la proprietà clone
screenshot

La versione alpha di Dragonfly non include le proprietà del prototipo di un oggetto nella vista delle variabili, così clone non appare. Ma ora avete imparato che la funzione clone esiste su tutti gli oggetti. Se abilitate l'impostazione "stop at a new script" e create un thread che richiama questo metodo, salterete direttamente ad esso.

Per trovare la definizione clone su Dragonfly:

  1. Spuntate l'opzione "stop at new script" con il pulsante dell'interfaccia mostrato nello screenshot che segue
  2. Incollate il codice che segue nella barra degli indirizzi della finestra di debug: javascript:void({}.clone());

Con una bookmarklet potete iniziare nuovi thread nel documento sottoposto a debug quando volete. Per esempio, potete provare il metodo javascript:void({}.clone());. Quando Dragonfly si blocca al nuovo thread, un click sul pulsante "step into" vi porta alla definizione problematica della proprietà clone.

Ed ecco la causa del bug 4: un metodo clone è aggiunto a tutti gli oggetti usando la sintassi Object.prototype. Questa è considerata una pratica cattiva perché usare for...in su oggetti farà vedere tutto quello che aggiungete a Object.prototype. Ciò può creare dei bug molto difficili da scovare.

Per correggere questo bug potete spostare il metodo clone così che sia definito direttamente sull'Object dell'oggetto invece che sul prototipo e poi correggere ogni chiamata a obj.clone in modo che diventino Object.clone(obj). Per esempio, evitate questo:

// BAD, don't do this:
Object.prototype.clone = function() {
    var obj = {};
    for (var prop in this) {
        obj[prop] = this[prop];
    }
    return obj;
}

// some code that demonstrates using the clone() method:
var myObj1 = { 'id': '1' };
var myObj2 = myObj1.clone();

E fate questo:

Object.clone = function(originalObject) {
    var obj = {};
    for (var prop in originalObject) {
        obj[prop] = originalObject[prop];
    }
    return obj;
}

// some code that demonstrates using the clone() method:
var myObj1 = { 'id': '1' };
var myObj2 = Object.clone(myObj1);

L'ultimo esempio impedisce la modifica di Object.prototype e così funziona meglio con altri script che usano loop del tipo for...in.

Bug da 5 a 7

Ora, caro lettore, devi proseguire per conto tuo. Usando le tue nuove conoscenze i bug 5, 6 e 7 puoi correggerli tu. Buona fortuna e buon divertimento.

Conclusioni

Questo articolo dimostra le basi dell'uso dei debugger e alcune tecniche avanzate di debugging Javascript. Avete imparato come impostare breakpoint sia dai debugger sia con gli script, come procedere passo a passo nel codice, come usare l'interfaccia utente dei debugger, come impostare breakpoint avanzati e come integrare bookmarklet nelle tecniche di debugging.

Se avete avuto problemi a seguire la parte più avanzata di questo articolo, non preoccupatevi. Anche padroneggiare inizialmente le basi vi migliorerà come sviluppatori.


Ti consigliamo anche