Een gedetailleerde handleiding voor het debuggen van JavaScript-code in Chrome Devtools. Fout vier: een ‘kloon’-attribuut dat er niet zou moeten zijn. Geminimaliseerde code opmaken

Stel je voor dat je aan deze ongelooflijke nieuwe webapplicatie werkt en dat je testers je hebben gevraagd de volgende bugs op te lossen:

  1. Het statusbalkbericht 'Bezig met laden...' verdwijnt niet wanneer de toepassing klaar is met laden.
  2. De standaardtaal is Noors, zelfs in de Engelse versies van IE en Firefox.
  3. Ergens in de code is een globale variabele prop gemaakt.
  4. Om de een of andere reden hebben alle elementen in de DOM-viewer het attribuut "kloon".

Foutopsporingsprogramma's uitvoeren

  • In Firefox moet u ervoor zorgen dat u het hebt geïnstalleerd Firebug-extensie. Selecteer “Extra > Firebug > Firebug openen”.
  • In Opera 9.5+ selecteert u 'Extra > Geavanceerd > Ontwikkeltools'.
  • Ga in IE bèta naar “Extra > Panelen > Explorer-balken > IE Developer Toolbar.”
  • Schakel in Safari of WebKit eerst het debug-menu (1) in en selecteer vervolgens “Ontwikkelen > Webinspecteur weergeven”
Het is tijd om de debuggers te starten. Omdat voor sommige instructies codewijzigingen nodig zijn, wilt u wellicht de testpagina opslaan en vanaf schijf in uw browser laden.

Fout #1: bericht 'Bezig met laden...'

Als u naar de toepassing kijkt waarvoor u fouten opspoort, ziet u eerst wat in figuur 1 wordt weergegeven.


rijst. 1: Eerste weergave van onze JavaScript-applicatie in respectievelijk Dragonfly en Firebug.

Als je kijkt bron Let in de debugger op de functie clearLoadingMessage() helemaal aan het begin van de code. Dit is een goede plek voor een controlepunt.

Hoe het te installeren:

  1. Klik in de linkermarge op het regelnummer om een ​​breekpunt op de eerste regel in te stellen
  2. Laad de pagina opnieuw.
Houd er rekening mee dat het breekpunt moet worden ingesteld op de coderegel die wordt uitgevoerd wanneer de functie wordt uitgevoerd. De regel die clearLoadingMessage() () bevat, is niet geschikt omdat het slechts een functiedefinitie is. Als u hier een breekpunt instelt, zal de debugger daar niet bij stoppen; het breekpunt moet binnen de functie worden ingesteld.

Wanneer de pagina opnieuw wordt geladen, stopt het script met draaien en ziet u wat in figuur twee wordt weergegeven.


rijst. 2: debuggers gestopt bij controlepunt binnen clearLoadingMessage.

Laten we eens kijken naar de functiecode. Zoals je gemakkelijk kunt zien, zijn er twee DOM-elementen daarin bijgewerkt en vermeldt regel 31 het woord statusbar. Het lijkt erop dat getElements("p", ("class"statusbar")).innerHTML zoekt naar het statusbar-element in de DOM-structuur. Hoe kunnen we onze aanname snel testen?

Plak deze verklaring in de opdrachtregel om te testen. Figuur drie toont drie schermafbeeldingen (Dragonfly, Firebug en IE8) na het lezen van innerHTML of outside HTML-element, geretourneerd door de opdracht die u onderzoekt.

Om dit te controleren, doet u het volgende:

  1. Zoek de opdrachtregel:
    * Schakel in Firebug naar het tabblad “Console”.
    * Kijk in Dragonfly onder het JavaScript-codepaneel.
    * Zoek in IE8 het tabblad "Console" aan de rechterkant.
  2. Plak getElements("p", ("class"statusbar")).innerHTML in de opdrachtregel.
  3. Druk op Enter.



rijst. 3: Voer het opdrachtresultaat uit in respectievelijk Dragonfly, Firebug en IE8.

De opdrachtregel is erg handig hulpmiddel, waarmee u snel kleine stukjes code kunt testen. De Firebug-console-integratie is erg handig: als uw opdracht een object uitvoert, krijgt u een zeer intelligent beeld. Als het bijvoorbeeld een DOM-object is, ziet u het gemarkeerde resultaat.

Je kunt de console gebruiken om diepgaander onderzoek te doen. JavaScript-tekenreeks, dat we bestuderen, doet de volgende drie dingen:

  1. Krijgt een verwijzing naar het statusbar-element.
  2. Vindt firstChild, met andere woorden, het eerste knooppunt in deze paragraaf.
  3. Stelt de eigenschap innerText in.
Laten we proberen iets meer uit te voeren dan de vorige opdracht in de console. U kunt bijvoorbeeld proberen uit te vinden wat de huidige waarde van de eigenschap innerText is voordat u er een nieuwe waarde aan toekent. Om hierachter te komen, kunt u de volledige opdracht tot aan het "=-teken op de opdrachtregel typen:
getElements( "p" , ("klasse" :"statusbar" )).firstChild.innerText

Verrassing, uiteindelijk... niets. De uitdrukking getElements("p",("class:"statusbar")).firstChild verwijst dus naar een object in het DOM dat geen tekst bevat, of geen innerText-eigenschap heeft.

Dan is de volgende vraag: wat komt er eigenlijk eerst? kind-element bij de paragraaf? Laten we deze vraag op de opdrachtregel stellen. (Zie vierde foto).

rijst. 4: opdrachtregel StDragonfly-foutopsporing, uitvoer [Tekstobject].

Dragonfly's debugger-uitvoer - [Tekstobject] laat zien dat het tekst is DOM-knooppunt. Zo vonden we de oorzaak van het eerste probleem. Een tekstknooppunt heeft geen eigenschap innerText, dus het instellen van p.firstChild.innerText op een waarde doet niets. Deze fout kan eenvoudig worden verholpen door innerText te vervangen door nodeValue, een eigenschap die is gedefinieerd door de W3C-standaard voor tekstknooppunten.

Nu we de eerste fout hebben afgehandeld:

  1. Klik op de knop of Uitvoeren om het script te voltooien.
  2. Vergeet niet het ingestelde controlepunt te resetten door nogmaals op het regelnummer te klikken.

Fout twee: taaldefinitieprobleem.

Mogelijk hebt u de variabele lang;/*taal*/ aan het begin van het script opgemerkt. Je zou kunnen vermoeden dat de code die de waarde van deze variabele instelt het probleem veroorzaakt. U kunt proberen deze code te vinden met behulp van de zoekfunctie die in debuggers is ingebouwd. In Dragonfly bevindt de zoekopdracht zich direct boven de codeviewer, in Firebug aan de rechterkant bovenste hoek(zie figuur 5)

Om erachter te komen waar het lokalisatieprobleem zich waarschijnlijk voordoet, doet u het volgende:

  1. Typ lang = in het zoekveld.
  2. Zet een breekpunt op de lijn waar lang variabele de waarde is ingesteld.
  3. Laad de pagina opnieuw.
WebInspector heeft ook zeer handige functie zoekopdracht. Hiermee kunt u tegelijkertijd naar alles zoeken in pagina-opmaak, CSS en JavaScript-code. De resultaten worden weergegeven in een apart paneel waar u erop kunt dubbelklikken om naar de gewenste locatie te gaan, zoals weergegeven in de schermafbeelding.


rijst. 5: Zoeken in Dragonfly en WebInspector.

Om te controleren wat deze functie doet:

  1. Klik op de knop "stap naar" om de getLanguage-functie te openen.
  2. Druk er herhaaldelijk op en voer de code stap voor stap uit
  3. Bekijk in het variabele weergavevenster hoe hun waarden veranderen.
Wanneer u de functie opent, ziet u een poging om de taal uit de browser user agent string te lezen door navigator.userAgent te analyseren.
var str1 = navigator.userAgent.match(/\((.*)\)/);
var ar1 = str1.split(/\s*;\s*/), lang;
voor (var i = 0; i< ar1.length; i++){
als (ar1[i].match(/^(.(2))$/))(
lang = ar1[i];
}
}


Terwijl u door uw code loopt, kunt u de Local Variables Viewer gebruiken. Figuur 6 laat zien hoe het eruit ziet in Firebug en IE8 DT; we hebben de ar1-array uitgebreid om de elementen ervan te zien.

rijst. 6: Paneel voor het bekijken van lokale variabelen van de getLanguage-functie in Firebug IE8's

De uitdrukking ar1[i].match(/^(.(2))$/) zoekt eenvoudigweg naar een tekenreeks die uit twee tekens bestaat, zoals “no”, “en”. Zoals u echter in de schermafbeelding in Firefox kunt zien, wordt informatie over de taal weergegeven in de vorm “nn-NO” (2). IE plaatst helemaal geen taalinformatie in de user-agent.

We hebben dus de tweede fout gevonden: de taal werd bepaald door te zoeken naar een code van twee letters in de user-agentregel, maar Firefox heeft een taalaanduiding van vijf tekens, en IE heeft die helemaal niet. Dergelijke code moet worden herschreven en vervangen door een taaldefinitie aan de serverzijde met behulp van HTTP de Accept-Language-header, of door deze op te halen van navigator.taal (navigator.userLanguage voor IE). Hier is een voorbeeld van wat zo'n functie zou kunnen zijn

functie getLanguage() (
var lang;

if (navigator.taal) (
lang = navigator.taal;
) else if (navigator.userLanguage) (
lang = navigator.userLanguage;
}

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

terugkeer lang;
}


Fout drie: de mysterieuze ‘prop’-variabele


rijst. 7: In het variabelenweergavepaneel Firebug en Dragonfly is de globale propvariabele zichtbaar

In Figuur 7 kun je duidelijk de “prop” variabele zien. In goed geschreven applicaties moet het aantal globale variabelen tot een minimum worden beperkt, omdat deze problemen kunnen veroorzaken wanneer bijvoorbeeld twee delen van de applicatie dezelfde variabele willen gebruiken. Laten we aannemen dat morgen een ander team nieuwe functies aan onze applicatie zal toevoegen en ook de variabele "prop" zal declareren. We eindigen met twee verschillende stukjes applicatiecode die dezelfde naam gebruiken voor verschillende dingen. Deze situatie leidt vaak tot conflicten en fouten. U kunt proberen deze variabele te vinden en deze lokaal te declareren. Om dit te doen, kun je de zoekopdracht gebruiken, zoals we in het vorige geval deden, maar er is een slimmere manier...

Debuggers voor veel andere programmeertalen hebben het concept van een ‘watch’, die in de foutopsporingsmodus gaat wanneer een opgegeven variabele verandert. Noch Firebug, noch Dragonfly ondersteunen momenteel "waarnemers", maar we kunnen soortgelijk gedrag eenvoudig nabootsen door toe te voegen volgende regel naar het begin van de code die wordt bestudeerd:

__defineSetter__( "prop" , function () (debugger; ));

Doe het volgende:
  1. Voeg foutopsporingscode toe aan het begin van het allereerste script.
  2. Laad de pagina opnieuw.
  3. Merk op hoe de uitvoering van het script wordt onderbroken.
IE8 DT heeft een tabblad “Bewaken”, maar er is geen onderbreking wanneer een variabele wordt gewijzigd. Dit voorbeeld werkt dus alleen in Firefox, Opera en Safari.

Wanneer u de pagina opnieuw laadt, stopt de uitvoering van de code onmiddellijk op de plaats waar de variabele "prop" is gedefinieerd. De daadwerkelijke stop vindt plaats op het punt waar u de bovenstaande regel hebt toegevoegd. Met één klik op de knop “stap uit” komt u op de locatie waar de variabele is ingesteld.

voor (prop in attributen) (
if (el.getAttribute(prop) != attributen) includeThisElement = false ;


Het is niet moeilijk om op te merken voor lus waarin de prop-variabele zonder wordt gedeclareerd trefwoord var, d.w.z. mondiaal. Het is niet moeilijk om dit op te lossen, voeg gewoon var toe en verhelp de fout.

Fout vier: een ‘kloon’-attribuut dat er niet zou moeten zijn

De vierde bug is blijkbaar ontdekt door een geavanceerde tester die de DOM-inspecteur gebruikt, aangezien het bestaan ​​ervan op geen enkele manier blijkt gebruikersinterface toepassingen. Als we de DOM-inspecteur openen (in Firebug is dit het tabblad “HTML”, in Dragonfly heet dit “DOM”), zullen we zien dat veel elementen een kloonattribuut hebben, dat er niet zou moeten zijn.

rijst. 8: De DOM-inspecteur van Dragonfly toont problematische code.

Omdat dit op geen enkele manier gevolgen heeft voor de gebruikers van de applicatie, mag deze bug niet als ernstig worden beschouwd, maar vergeet niet dat deze de prestaties aanzienlijk kan beïnvloeden, aangezien het script het attribuut op honderden en duizenden elementen instelt.

Meest snelle manier De oplossing voor dit probleem is het instellen van een breekpunt dat wordt geactiveerd wanneer een attribuut met de naam kloon wordt ingesteld op een HTML-element. Kunnen debuggers dit doen?

JavaScript is een zeer flexibele taal, en een van zijn sterke punten(of zwakke, afhankelijk van uw standpunt) is wat u kunt vervangen basisfuncties taal met uw eigen taal. Voeg dit stukje code toe aan de pagina, het zal overschrijven systeem methode setAttribute, waardoor de code stopt wanneer de eigenschap "clone" is ingesteld:

var funcSetAttr = Element.prototype.setAttribute; /* bewaar een verwijzing naar de systeemmethode */
Element.prototype.setAttribute = functie (naam, waarde) (
if (naam == "kloon" ) (
debugger; /* stop het script */
}
funcSetAttr.call(deze, naam, waarde); /* roep een eerder opgeslagen systeemmethode aan, zodat de normale eigenschappen correct worden ingesteld */
};


Wij doen dus het volgende:
  1. Voeg de volgende code toe aan het begin van het eerste script op de pagina.
  2. Laad de pagina opnieuw.
Na een herstart begint het script met het verwerken van de DOM-boom, maar stopt onmiddellijk zodra er een “slecht” attribuut wordt ingesteld. (Houd er rekening mee dat actueel Firefox-versies, is de implementatie van setAttribute anders voor verschillende elementen. De bovenstaande code werkt altijd zoals het hoort, alleen in Opera; Om hetzelfde effect in Firefox te krijgen, kunt u het woord Element vervangen door HTMLFormElement om de meer specifieke HTMLFormElement.prototype.setAttribute-methode te overschrijven.

Wanneer de uitvoering stopt bij een breekpunt, wil je weten waar de setAttribute()-aanroep plaatsvond, wat betekent dat je terug moet gaan in de functie-aanroepketen om te zien wat daar gebeurt. Hiervoor kunt u een call-stack gebruiken.


rijst. 9: Call-stack in Dragonfly en IE8.

Figuur 10 toont de stapel in Firebug. In de rij " setAttribuut " Naast de bestandsnaam is de meest linkse functie de momenteel aangeroepen functie.


rijst. 10: Roep stapel op in Firebug. De meest recent aangeroepen functie aan de linkerkant.

Door op de namen van functies op de stapel te klikken, kunt u bepalen hoe u op dit punt bent gekomen. Het is belangrijk om het zelf te proberen om te begrijpen hoe het werkt. Houd er rekening mee dat terwijl u door de stapel navigeert, de inhoud van het deelvenster Lokale variabelen ook wordt bijgewerkt om hun status weer te geven op het moment dat de geselecteerde functie werd uitgevoerd.

Hoe de call-stack te gebruiken om de problematische functie te vinden:

  1. Klik op de naam van de functie in de stapel die u wilt zien.
  2. Houd er rekening mee dat lokale variabelen worden bijgewerkt naar de waarden die ze in de geselecteerde context hebben.
  3. Onthoud dat als u de stapknoppen gebruikt, deze u van de breekpuntlocatie zullen verplaatsen, zelfs als u zich in een ander deel van de stapel bevindt.
Als u makeElement selecteert, gaan we naar een ander deel van de code:
for (var prop in attributen) (
el.setAttribute(prop, attributen);
}


waar u de setAttribute-oproep ziet. Het paneel Lokale variabelen laat zien dat de waarde van de variabele "prop" inderdaad "kloon" is. De prop-variabele wordt gedefinieerd in een for...in-lus. Dit vertelt ons dat dit de naam is van een van de eigenschappen van het object “attributen”. Dit object wordt als tweede parameter aan de functie doorgegeven. Als je nog een niveau hoger op de stapel gaat, zie je de volgende code:
var formulier = makeElement('formulier', (actie:’/login’, methode:’post’, naam:’loginform’ ), document.body);

De tweede parameter van de methode is vetgedrukt: dit object heeft geen klooneigenschap. Dus waar kwam het vandaan?

Laten we nog eens teruggaan naar de functie makeElement en de attribuutvariabele en zijn eigenschap "kloon" nader bekijken. U kunt op de functiewaarde van deze eigenschap klikken om naar de plaats te gaan waar deze is toegewezen, deze wordt blauw gemarkeerd

rijst. 11: Firebug laat ons zien waar de klooneigenschap is gedefinieerd.

We hebben dus de oorzaak van de vierde fout gevonden: de kloonmethode wordt toegevoegd aan alle objecten die Object.prototype gebruiken. Deze aanpak wordt als een slechte praktijk beschouwd, omdat in for...in-lussen op objecten alle eigenschappen die u instelt via Object.prototype zichtbaar zullen zijn. Dit kan tot zeer subtiele fouten leiden.

Om deze fout te verhelpen, kunt u de kloonmethode van het prototype van het object rechtstreeks naar het object zelf verplaatsen en vervolgens alle aanroepen van obj.clone() vervangen door Object.clone(obj), zoals weergegeven in het voorbeeld:

// SLECHT, je zou dit niet moeten doen
Object.prototype.kloon = functie() (
var obj = ();
voor (var prop hierin) (
obj = dit;
}
retour obj;
}
// Code. het demonstreren van het gebruik van de clone() methode:
var myObj1 = ("id": "1");
var mijnObj2 = mijnObj1.kloon();

Doe het beter zo:

Van de auteur: console.log kan u veel over uw toepassing vertellen, maar u kunt er niet echt fouten in uw code mee opsporen. Met de nieuwe JS-debugger in Firefox kunt u sneller en zonder bugs code schrijven. Een artikel over het werkingsprincipe van deze debugger.

In dit voorbeeld openen we een heel eenvoudige applicatie die het debuggen van JavaScript eenvoudig maakt. De applicatie zelf draait op eenvoudige open source JS-frameworks. Open het in de nieuwste Firefox Developer Edition en start debugger.html met de sneltoets Option + Cmd + S op Mac of Shift + Ctrl + S op Windows. De debugger is verdeeld in 3 panelen: een bestandenlijstpaneel, een codepaneel en een werkbalk.

De werkbalk is onderverdeeld in werkbalken, kijkuitdrukkingen, breekpunten, oproepstapel en gebieden.

Stop met het gebruik van console.log

We willen console.log gebruiken om onze code te debuggen. We voegen gewoon een aanroep toe aan de code om de waarde van de variabele te achterhalen, en dat is alles, toch? Deze aanpak zal werken, maar is omslachtig en tijdrovend. In dit voorbeeld doorlopen we de toepassing met behulp van debugger.html om de waarde van een variabele te vinden.

Met debugger.html kun je dieper in je code duiken door simpelweg een breekpunt aan een regel toe te voegen. Breekpunten pauzeren de debugger zodat u de code kunt bekijken. In dit voorbeeld voegen we een breekpunt toe op regel 13 van het bestand app.js.

Voeg nu de taak toe aan de lijst. De code stopt bij de addTodo-functie en we kunnen naar de waarde van het veld in de code kijken. Beweeg over een variabele om de waarde ervan te zien, enz. Zo kunt u ankers, applets, onderliggende elementen, enz. bekijken:

Dezelfde informatie is te vinden in het paneel Gebieden.

Wanneer het script is gepauzeerd, kunt u de regels stap voor stap uitvoeren met behulp van de werkbalk. De knoppen Hervatten/Pauze doen precies wat ze zeggen. De Step-knop voert de huidige coderegel uit, Enter – gaat naar de functie, Exit – voert de huidige functie uit voordat de oproep wordt verlaten.

Controleer de waarde van een monovariabele ook met behulp van watch-expressies. Voer eenvoudigweg een expressie in het vak Expressions to Watch in en de debugger zal ernaar kijken terwijl uw code wordt uitgevoerd. In het bovenstaande voorbeeld kunt u titel- en to-do-expressies toevoegen en de debugger zal de waarden opsplitsen wanneer deze beschikbaar zijn. Vooral handig wanneer:

Je stapt door de code en ziet de waarde veranderen;

U debugt vaak dezelfde code en wilt gemeenschappelijke waarden zien;

Je probeert erachter te komen waarom die verdomde knop niet werkt.

U kunt ook fouten in React/Redux-toepassingen debuggen met debugger.html. Hoe werkt dit:

Navigeer naar de component waarvoor u fouten wilt opsporen.

Zie het componentendiagram aan de linkerkant (functies in een klasse).

Voeg breekpunten toe aan de juiste functies.

Druk op pauze en bekijk de eigenschappen en statussen van het onderdeel.

De call-stack is vereenvoudigd, zodat je applicatiecode vermengd ziet met het framework.

met debugger.html kunt u naar verwarrende of verkleinde code kijken die fouten kan veroorzaken. Vooral handig bij het werken met veelgebruikte raamwerken zoals React/Redux. De debugger kent de component waarop u hebt gepauzeerd en toont een vereenvoudigde call-stack, componentdiagram en eigenschappen. Hieronder legt ontwikkelaar Amit Zur uit hoe hij de Firefox-codedebugger op JS Kongress gebruikt:

Als je de nieuwe debugger.html van dichterbij wilt bekijken, ga dan naar de Mozilla Developer Playground. We hebben een reeks tutorials gemaakt om ontwikkelaars te helpen leren hoe ze de tool effectief kunnen gebruiken om code te debuggen.

Open source-ontwikkelaarstools

Het debugger.html-project werd ongeveer 2 jaar geleden gelanceerd, samen met een volledige herziening van Firefox DevTools. We wilden DevTools naar moderne technologieën brengen en deze openstellen voor ontwikkelaars over de hele wereld. En omdat de technologie open is, kan deze vrijelijk uitgroeien tot iets dat de kleine groep bij Mozilla zich nooit had kunnen voorstellen.

JS vormt de basis van elke geavanceerde webapplicatie, dus een krachtige debugger was een kernonderdeel van de toolkit. We wilden iets maken dat snel, gebruiksvriendelijk en aanpasbaar is en dat in staat is om elk nieuw JS-framework te debuggen. We besloten populaire webtechnologieën te gebruiken omdat we dichter bij de gemeenschap wilden werken. Deze aanpak zou de debugger zelf verbeteren - als we Webpack zouden adopteren en de build-tool en bronkaarten intern zouden gaan gebruiken, zouden we de brontoewijzing en het hot reloaden willen verbeteren.

debugger.html is geschreven in React, Redux en Babel. React-componenten zijn lichtgewicht, testbaar en eenvoudig te ontwerpen. Voor snelle UI-prototyping en documentatie van algemene componenten gebruiken we React Storybook. Dit maakt het gemakkelijker om met verschillende JS-frameworks (zoals React) te werken. Met de front-end van Babel kun je dingen doen zoals het weergeven van de Component-klasse en zijn functies in de linkerzijbalk. We kunnen ook breekpunten instellen voor functies, zodat deze niet bewegen als u de code wijzigt.

Redux-acties zijn een pure UI-API. Ze kunnen echter ook worden gebruikt om een ​​onafhankelijke JS Debugger CLI te maken. De Redux-repository heeft selectors waarmee u de huidige foutopsporingsstatus kunt opvragen. Onze unit-tests voeren Redux-acties uit en simuleren browserreacties. Integratietests brengen de browser in actie met Redux-foutopsporingsacties. De functionele architectuur zelf is ontworpen om te testen.

We hebben bij elke stap op de Mozilla-ontwikkelaarsgemeenschap vertrouwd. Het project werd gepubliceerd op GitHub en ons team heeft ontwikkelaars over de hele wereld benaderd en zij hebben gereageerd. Helemaal in het begin waren geautomatiseerde tests van cruciaal belang voor de gemeenschap. De tests voerden regressie uit en documenteerden gedrag dat gemakkelijk over het hoofd kon worden gezien. Daarom was een van de eerste stappen het schrijven van unit-tests voor Redux-acties en Flow-typen voor de Redux-winkel. In feite zorgde de gemeenschap ervoor dat de dekking van Flow en Jest ervoor zorgde dat elk bestand werd geschreven en getest.

Als ontwikkelaars zijn wij van mening dat tools sterker worden naarmate er meer ontwikkelaars bij betrokken zijn. Ons kernteam is altijd klein geweest (2 personen), maar gemiddeld waren er 15 assistenten per week. De community gaf ons verschillende perspectieven, waardoor we op uitdagingen konden anticiperen en functies konden schrijven die we ons nooit hadden kunnen voorstellen. We formatteren momenteel call-stacks voor 24 bibliotheken. Van veel daarvan wisten we niet eens. We tonen ook Webpack- en Angular-kaarten in de bronboom.

We zijn van plan alle Firefox DevTools naar GitHub te verplaatsen, zodat meer mensen ze kunnen gebruiken en verbeteren. Wij aanvaarden uw hulp graag. U kunt naar onze projectpagina debugger.html op GitHub gaan. We hebben een hele lijst met instructies geschreven voor het uitvoeren van de debugger op uw computer, waar u alles kunt wijzigen wat u maar wilt. Gebruik het om JS-code voor wat dan ook te debuggen: browsers, terminals, servers, telefoons, robots. Als je iets ziet dat verbeterd kan worden, schrijf ons dan op GitHub.

Van tijd tot tijd maken ontwikkelaars codeerfouten. Een fout in een programma of script wordt een bug genoemd.

Het proces van het vinden en herstellen van fouten wordt debugging genoemd en is een normaal onderdeel van het ontwikkelingsproces. In deze sectie worden hulpmiddelen en technieken besproken die u kunnen helpen bij het opsporen van fouten in taken.

Foutmeldingen in IE

De eenvoudigste manier om fouten op te sporen is door foutrapportage in uw browser in te schakelen. Standaard toont Internet Explorer een foutpictogram in de statusbalk wanneer er een fout optreedt op een pagina.

Als u dubbelklikt op dit pictogram, gaat u naar een dialoogvenster met informatie over de specifieke fout.

Omdat dit pictogram gemakkelijk over het hoofd wordt gezien, biedt Internet Explorer u de mogelijkheid om automatisch een foutdialoogvenster weer te geven wanneer er een fout optreedt.

Om deze optie in te schakelen, selecteert u Extra → Internetopties → tabblad Geavanceerd. en vink ten slotte het selectievakje "Melding weergeven bij elk script" aan, zoals hieronder weergegeven -

Foutmeldingen in Firefox of Mozilla

Andere browsers, zoals Firefox, Netscape en Mozilla, sturen foutmeldingen naar een speciaal venster dat de JavaScript-console of Error Console wordt genoemd. Om de console te bekijken, selecteert u Extra → Foutconsole of Webontwikkeling.

Omdat deze browsers geen visuele informatie bieden wanneer er een fout optreedt, moet u de console helaas open houden en op fouten letten terwijl uw script wordt uitgevoerd.

Foutmeldingen

Foutmeldingen die in de console of via de dialoogvensters van Internet Explorer worden weergegeven, zijn het resultaat van zowel syntaxis- als runtimefouten. Deze foutmeldingen bevatten het regelnummer waarop de fout is opgetreden.

Als u Firefox gebruikt, kunt u op de beschikbare fout in de foutconsole klikken om naar de exacte regel in het script met de fout te gaan.

Hoe een script te debuggen

Er zijn verschillende manieren om uw JavaScript te debuggen - Gebruik JavaScript Validator

Eén manier om JavaScript-code op vreemde fouten te testen, is door deze door een programma te laten lopen dat de code controleert om er zeker van te zijn dat deze geldig is en dat deze de officiële syntaxisregels van de taal volgt. Deze programma's worden parsers genoemd, of kortweg validators, en worden vaak geleverd met commerciële HTML- en JavaScript-editors.

De handigste validator voor JavaScript is JavaScript Lint van Douglas Crockford, die gratis beschikbaar is in JavaScript Lint van Douglas Crockford.

Bezoek eenvoudigweg deze webpagina, plak de JavaScript-code (alleen JavaScript) in het daarvoor bestemde tekstgebied en klik op de jslint-knop. Dit programma analyseert uw JavaScript-code en zorgt ervoor dat alle variabelen- en functiedefinities de juiste syntaxis volgen. Het controleert ook JavaScript-instructies, zoals if en while, om er zeker van te zijn dat ze ook het juiste formaat hebben

Voeg foutopsporingscode toe aan uw programma's

U kunt de methoden alert() of document.write() in uw programma gebruiken om fouten in uw code op te sporen. Je zou bijvoorbeeld zoiets als dit kunnen schrijven:

var-foutopsporing = waar; var whoImage = "widget"; if(debugging) alert("Roept swapImage() aan met argument: " + WhichImage); var swapStatus = swapImage(welkeAfbeelding); if(debugging) alert("Verlaat swapImage() met swapStatus=" + swapStatus);

Door de inhoud en volgorde van alert() te onderzoeken zoals deze verschijnt, kunt u eenvoudig de functionaliteit van uw programma testen.

Hoe u de JavaScript-foutopsporing gebruikt

Een debugger is een applicatie waarin alle aspecten van de scriptuitvoering onder controle staan ​​van de programmeur. Debuggers bieden fijnmazige controle over de status van een script via een interface waarmee u waarden kunt inspecteren en instellen en de uitvoeringsstroom kunt controleren.

Zodra het script in de debugger is geladen, kan het regel voor regel worden uitgevoerd of de opdracht krijgen om bij specifieke breekpunten te stoppen. Wanneer de uitvoering wordt gestopt, kan de programmeur de status van het script en zijn variabelen controleren om te bepalen of er iets mis is. U kunt ook variabelen bekijken om hun waarden te wijzigen.

  • Gebruik veel commentaar. Met opmerkingen kunt u uitleggen waarom u het script op de manier heeft geschreven en bijzonder moeilijke delen van de code uitleggen.
  • Gebruik altijd inspringing om uw code gemakkelijk leesbaar te maken. Door inspringen kunt u ook gemakkelijker begin- en eindtags, accolades en andere HTML- en scriptelementen op elkaar afstemmen.
  • Schrijf modulaire code. Groepeer uw uitspraken indien mogelijk in functies. Met functies kunt u met minimale inspanning gerelateerde instructies groeperen en stukjes code testen en hergebruiken.
  • Wees consistent in de naamgeving van uw variabelen en functies. Probeer namen te gebruiken die lang genoeg zijn om betekenisvol te zijn en de inhoud van een variabele of het doel van een functie te beschrijven.
  • Gebruik consistente syntaxis bij het benoemen van variabelen en functies. Met andere woorden, gebruik kleine letters of hoofdletters; als u de Camel-Back-notatie verkiest, gebruik deze dan consequent.
  • Controleer lange scripts modulair. Met andere woorden: probeer niet het hele script te schrijven voordat u een deel ervan hebt getest. Schrijf het onderdeel en voer het uit voordat je het volgende deel van de code toevoegt.
  • Gebruik beschrijvende namen voor variabelen en functies en vermijd het gebruik van namen die uit één teken bestaan.
  • Let op de citaten. Houd er rekening mee dat aanhalingstekens in paren rond tekenreeksen worden gebruikt en dat beide aanhalingstekens dezelfde stijl moeten hebben (een of twee).
  • Houd uw gelijktekens bij. Gebruik er geen = voor vergelijkingsdoeleinden.
  • Ik declareer variabelen expliciet met het trefwoord var.

Als het gaat om het vinden van de oorzaak van fouten, kan het kennen van uw tool het verschil maken. Ook al heeft JavaScript de reputatie moeilijk te debuggen te zijn, als u een paar trucjes kent, zal het minder tijd kosten om de oorzaak van de fout te vinden.

We hebben een lijst met 14 foutopsporingstips samengesteld, waarvan u misschien nog niet op de hoogte bent, maar die u kunnen helpen bij het debuggen van JavaScript-code.

De meeste van deze tips zijn voor Chrome en Firefox, hoewel de meeste werken in ontwikkeltools voor andere browsers.

1. 'foutopsporing;'

Na console.log, ‘debugger;‘mijn favoriete snelle en vuile foutopsporingstool. Zodra u het aan uw code toevoegt, stopt Chrome op dat moment automatisch met het uitvoeren van de code. Je kunt hem zelfs zo verpakken dat hij alleen ontsteekt als je hem nodig hebt.

Als (dit ding) (debugger; )

2. Objecten weergeven als tabellen

Soms hebt u een complexe reeks objecten die u wilt bekijken. Je kunt gebruiken console.log om ze weer te geven, en blader vervolgens door een enorme lijst, of gebruik console.tafel. Dit maakt het veel gemakkelijker om te begrijpen waar u mee te maken heeft.

Var dieren = [ ( dier: "Paard", naam: "Henry", leeftijd: 43 ), ( dier: "Hond", naam: "Fred", leeftijd: 13 ), ( dier: "Kat", naam: " Frodo", leeftijd: 18 ) ]; console.table(dieren);

3. Probeer met verschillende resoluties te kijken

Het zou geweldig zijn om een ​​mobiel apparaat op je bureau te hebben, maar in de echte wereld is dit niet mogelijk. Hoe kan ik het formaat van de viewport wijzigen? Chrome biedt je alles wat je nodig hebt. Ga naar Developer Tools en klik vervolgens op de knop Apparaatmodus wisselen. Zie hoe uw media-uitingen tot leven komen!

4. Zoek snel naar DOM-elementen

Selecteer een DOM-element in de Toolbox en open het vervolgens in de console. De dev-tools van Chrome onthouden de laatste vijf elementen: het laatst geselecteerde element $0, het op een na laatste geselecteerde element $1, enz.

Als je de volgende elementen hebt geselecteerd in de volgorde 'item-4', 'item-3', 'item-2', 'item-1', 'item-0', dan heb je toegang tot DOM-elementen zoals weergegeven in consoles:

5. Uitvoeringstijd van code meten met console.time() en console.timeEnd()

Het kan erg handig zijn om te weten hoe lang het duurt om een ​​stukje code uit te voeren, vooral bij het debuggen van langzame lussen. U kunt meerdere benoemde timers instellen. Laten we een voorbeeld bekijken:

Console.time("Timer1"); var-items = ; for(var i = 0; ik< 100000; i++){ items.push({index: i}); } console.timeEnd("Timer1");

Deze code levert het volgende resultaat op:

6. Een stacktracering verkrijgen voor een functie

U weet waarschijnlijk dat JavaScript-frameworks veel code bevatten.

Deze code rendert de interface en activeert gebeurtenissen, dus uiteindelijk zul je willen weten waardoor de functie werd aangeroepen.

Omdat JavaScript geen erg gestructureerde taal is, is het soms handig om informatie te krijgen over wat er is gebeurd en wanneer. Op dit moment komt hij het podium op console.trace.

Stel je voor dat je de volledige call-stack voor een functie wilt zien funcZ in kopie auto op lijn 33.

Var-auto; var func1 = function() ( func2(); ) var func2 = function() ( func4(); ) var func3 = function() ( ) var func4 = function() ( auto = nieuwe auto(); car.funcX( ) var Auto = functie() ( this.brand = 'volvo'; this.color = 'rood'; this.funcX = function() ( this.funcY(); ) this.funcY = function() ( this); .funcZ(); dit.funcZ = function() ( console.trace('trace auto') ) func1(); var auto; var func1 = function() ( func2(); ) var func2 = function() ( func4(); ) var func3 = function() ( ) var func4 = function() ( auto = nieuwe auto(); car.funcX( ) var Auto = functie() ( this.brand = 'volvo'; this.color = 'rood'; this.funcX = function() ( this.funcY(); ) this.funcY = function() ( this); .funcZ(); ) this.funcZ = function() ( console.trace('trace auto'); ) ) func1();

Nu zien wij dat func1 oorzaken func2, wat veroorzaakt func4. Func4 creëert een exemplaar Auto en roept vervolgens de functie aan auto.funcX enz.

Zelfs als u denkt dat u het programma-uitvoeringsscript goed kent, kan dit erg handig zijn. Stel dat u uw code wilt verbeteren. Ontvang een stacktrace en een lijst met alle bijbehorende functies, die allemaal zichtbaar zijn.

7. Verkleinde code opmaken

Soms kun je tijdens de productie een probleem tegenkomen, maar staan ​​je bronkaarten niet op de server. Het is oké. Chrome kan uw JavaScript-bestanden opmaken in een beter leesbare indeling. Natuurlijk zal de code niet zo informatief zijn als de broncode, maar je kunt tenminste begrijpen wat erin gebeurt. Klik op de knop {} « Mooie afdruk", gelegen onder de codeviewer in de inspecteur.

8. Debug snel een functie

Stel dat u een breekpunt aan een functie wilt toevoegen.

Er zijn twee meest voorkomende manieren om dit te doen:

  1. Zoek de gewenste regel in het infovenster en voeg een breekpunt toe
  2. Voeg debugger toe aan uw script

Voor beide oplossingen is het nodig dat u het juiste bestand en de juiste regel vindt waarvoor u fouten wilt opsporen.

Het gebruik van een console voor dit doel komt waarschijnlijk minder vaak voor. Gebruik debug(funcNaam) in de console en het script pauzeert wanneer het de gewenste functie bereikt.

Dit is een zeer snelle methode, maar werkt niet op privé- en anonieme functies. Maar als uw situatie anders is, is dit waarschijnlijk de snelste manier om de functie te debuggen. (Opmerking van de auteur: er is een functie console.debug, wat nodig is voor een ander.)

Var func1 = functie() ( func2(); ); var Auto = function() ( this.funcX = function() ( this.funcY(); ) this.funcY = function() ( this.funcZ(); ) ) var car = nieuwe auto();


9. Scripts waarvoor geen foutopsporing vereist is

10. Vind belangrijke dingen met geavanceerdere foutopsporingstechnieken

Complexere foutopsporingsscenario's kunnen veel uitvoerregels vereisen. Eén manier om de uitvoer te structureren is door verschillende consolefuncties te gebruiken. Bijvoorbeeld console.log, console.debug, console.warn, console.info, console.error, enz. U kunt ze vervolgens filteren in de inspecteur. Maar soms is dit niet precies wat u nodig heeft bij het debuggen. Nu kunt u creatief aan de slag en uw eigen console-uitvoerformaten maken met behulp van CSS.

Console.todo = function(msg) ( console.log(' % c % s % s % s', 'kleur: geel; achtergrond - kleur: zwart;', '–', msg, '–'); ) console .important = function(msg) ( console.log(' % c % s % s % s', 'kleur: bruin; lettertype - gewicht: vet; tekst - decoratie: onderstrepen;', '–', msg, '– '); ) console.todo(“Dit is iets dat moet worden opgelost”); console.important(‘Dit is een belangrijke boodschap’);


11. Volg functieaanroepen en functieargumenten.

In de Chrome-console kunt u bepaalde functies volgen. Elke keer dat een functie wordt aangeroepen, wordt deze samen met de parameters die eraan worden doorgegeven, geregistreerd.

Var func1 = functie(x, y, z) ( //.... );

Dit is een goede manier om te zien met welke argumenten een functie wordt aangeroepen. Maar ik moet zeggen dat het leuk zou zijn als de console zou kunnen bepalen hoeveel argumenten hij kan verwachten. In het bovenstaande voorbeeld func1 verwacht drie argumenten, maar er worden er slechts twee aangenomen. Als dit niet in de code wordt afgehandeld, kan dit tot een fout leiden.

12. Snelle toegang tot elementen in de console

Een snellere manier om querySelector in de console te gebruiken is door $. $('css-selector') retourneert het eerste overeenkomende element, en $$('css-selector') retourneert alle overeenkomende elementen. Als u een element meerdere keren gebruikt, kunt u het opslaan in een variabele.

13. Postman is geweldig (maar Firefox is sneller)

Veel ontwikkelaars gebruiken Postman om AJAX-verzoeken te testen.

Soms is het gemakkelijker om voor deze doeleinden een browser te gebruiken.

Wanneer u zich geen zorgen meer hoeft te maken over login-cookies als u op een met een wachtwoord beveiligde pagina werkt. Hier leest u hoe u verzoeken in Firefox kunt bewerken en opnieuw kunt verzenden.

Open de inspecteur en ga naar het tabblad Netwerk. Klik met de rechtermuisknop op het verzoek waarin u geïnteresseerd bent en selecteer vervolgens 'Bewerken' en 'Opnieuw verzenden'. Nu kunt u alles wijzigen: corrigeer de titel, bewerk de parameters en klik op “Opnieuw verzenden”.

Hieronder heb ik een voorbeeld gegeven van een verzoek dat meerdere keren is verzonden met verschillende parameters:

14. Breekpunt wanneer een DOM-element verandert

De DOM kan grappig zijn. Soms veranderen elementen erin om redenen die u niet kent. Wanneer u echter JavaScript moet debuggen, kunt u met Chrome de uitvoering van de code pauzeren wanneer een DOM-element verandert. Klik met de rechtermuisknop op het gewenste element in de inspecteur en selecteer een voorwaarde om de uitvoering te stoppen.

Gepubliceerd: 26 maart 2013

Chrome Developer Tools is naar mijn mening de handigste tool voor webontwikkeling. Het bevat alle noodzakelijke functionaliteit voor het maken en debuggen van volwaardige webapplicaties. Maar net als bij elk ander hulpmiddel moet u ermee leren werken. Laten we beginnen met de basis.

De console speelt de rol van een interactieve JavaScript-interpreter. Het geeft ook fouten weer die optreden terwijl de webapplicatie actief is. Naast een apart tabblad is de console beschikbaar op alle andere tabbladen door op Esc te drukken of op het consolepictogram linksonder in het scherm.

De console geeft de ontwikkelaar toegang tot een aantal handige en nuttige functies. Laten we de belangrijkste bekijken:

console.log() , console.error() , console.warn() en console.debug()

Met basisconsole-uitvoerfuncties kunt u willekeurige berichten naar de console uitvoeren. Ze verschillen in de classificatie van uitvoerberichten: error() markeert berichten als fouten, warn() markeert berichten als waarschuwingen, debug() markeert berichten als foutopsporing.

Deze functies accepteren een onbeperkt aantal parameters, waardoor u meerdere variabelen achter elkaar kunt weergeven en ze zelfs tot hele zinnen kunt samenvoegen:

Console.log("Logtijd:", 1121102802);

Er is ook opmaakondersteuning:

Console.log("Logtijd: %d", 1121102802);

Ondersteunde formaatindicatoren:

// %s — string console.log("%s", "Hallo"); // %d, %i — geheel getal console.log("%d", 1337/42); // %f is een drijvende-kommagetalconsole.log("%f", 1337/42); // %o is een DOM-element console.log("%o", document.body); // ofwel console.dirxml(document.body); // %O is een JavaScript-element console.log("%O", document.body); // ofwel console.dir(document.body); // %c — uitvoer met instelling van CSS-stijlen console.log("%chello %cworld", "kleur: rood", "kleur: blauw");

console.trace()

Drukt de call-stack af vanaf het punt in de code waar de methode is aangeroepen. De call-stack bevat bestandsnamen en regelnummers plus een aantal oproepen naar de trace()-methode vanaf hetzelfde punt.

console.assert()

De assert-functie controleert de expressie die als eerste parameter is doorgegeven, en als de expressie false is, schrijft hij samen met de call-stack een fout naar de console:

Var twee = 3; var drie = 2; console.assert(twee< three, "два меньше трех");

console.group() , console.groupCollapsed() en console.groupEnd()

Functies voor het groeperen van uitvoer. De functie group() opent een berichtengroep, neemt de groepsnaam als parameter (opmaak wordt ondersteund zoals in console.log()) en de functie groupEnd() sluit de laatst geopende groep. De functie groupCollapsed() is vergelijkbaar met de functie group(), maar de berichtengroep die wordt gemaakt, is standaard samengevouwen.

console.time() en console.timeEnd()

Functies voor het berekenen van de uitvoeringstijd van code. De functie time() start een timer, en de functie timeEnd() stopt de timer en drukt de waarde ervan af. Beide functies accepteren de timernaam als vereiste parameter.

Berichtenfilter

In de rechter benedenhoek van het consoletabblad bevindt zich een berichtenfilter op type. Alles komt overeen met alle berichten, Fouten - fouten en de uitvoer van de console.error() functie, Waarschuwingen - waarschuwingen en de uitvoer van de console.warn() functie, Logboeken - de uitvoer van de console.log() functie, Debug - de uitvoer van console.debug() , consolefuncties .timeEnd() en andere informatie.

Interactie met andere tabbladen

debugger;

Wanneer de browser de debuggerregel bereikt; in elke code stopt het op dit punt automatisch de uitvoering van het script en gaat het naar het tabblad Scripts (Bronnen).

$() , $$() en $x()

Functies die het selecteren van elementen eenvoudiger maken, werken alleen in de console. De functie $() retourneert het eerste element dat overeenkomt met de geselecteerde selector. De tweede parameter kan worden gebruikt om de zoekcontext door te geven:

$("head") // retourneert het head-element $("head", document.body) // retourneert null omdat body geen head-elementen bevat

De functie $$() is vergelijkbaar met $() , maar retourneert alle gevonden elementen:

$$("script") // retourneert alle scriptelementen $$("script", document.body) // retourneert alle scriptelementen in de body

De functie $x() retourneert alle elementen die overeenkomen met de XPath-expressie. De tweede parameter kan worden gebruikt om de context door te geven:

$x("//script") // retourneert alle scriptelementen $x("script", document.body); // retourneert alle scriptelementen die rechtstreeks in de body voorkomen

Veel JavaScript-frameworks definiëren hun eigen $()-functie, en daarom verandert ook de betekenis van de functies in de console.

$0 — $4

De console slaat in het geheugen verwijzingen op naar de laatste vijf elementen die zijn geselecteerd op het tabblad Elementen. Om toegang te krijgen tot deze variabelen worden de variabelen $0, $1, $2, $3 en $4 gebruikt. $0 slaat een link op naar het momenteel geselecteerde element, $1 naar het vorige, enzovoort.

$_

De variabele $_ slaat het resultaat op van het uitvoeren van de laatste opdracht in de console. Hierdoor kan het resultaat van het ene commando in een ander commando worden gebruikt. Probeer deze opdrachten één voor één:

1337/42; console.log("%d", $_);

inspecteren()

De functie inspect() opent het doorgegeven object of element op het bijbehorende tabblad:

Inspect($("head script")) // opent het tabblad Elementen en markeert de eerste scripttag die in head wordt gevonden