Lesson Wednesday

This is the second of four lessons on debugging in JavaScript. Previously, we've covered working with your DevTools console open and keeping an eye out for console errors. In this lesson, we've intentionally added two errors to our Mad Libs project so that we can learn how to use console.log() statements to help us debug. In the process, we'll also cover a very common error for JavaScript beginners — and how to easily spot it.

This lesson includes instructions for coding along, but you are welcome to simply read through this lesson if you prefer.

Using console.log()


console.log() is a very commonly used tool in the JavaScript developer's toolbox. This method does exactly what it sounds like: logs a message to the console. In order to read the logged messages, the DevTools console must be open.

The console object itself is a Web API (tools/structures that web browsers provide to developers) and it represents and provides access to the browser's DevTools console. We won't work with much beyond the console.log method in the program, but there are other properties to explore including other ways to print text to the console. Check out the reference page for console on MDN.

Finding the First Error

Let's drop a few console.log() statements into our Mad Libs script file. Remember, we've intentionally added an error to our Mad Lib's scripts.js. If you are coding along with this lesson, copy and paste the following JS into your scripts.js file of your Mad Libs project.

js/scripts.js
window.onload = function() {
  // new line below
  console.log("Script executing!");

  let form = document.querySelector("form");
  form.onsubmit = function(event) {
    // new line below
    console.log("Submit form successfully reached.");
    const person1Input = document.getElementById("person1Input").value;
    const person2Input = document.getElementById("person2Input").value;
    const animalInput= document.getElementById("animalInput").value;
    const exclamationInput = document.getElementById("exclamationInput").value;
    const verbInput = document.getElementById("verbInput").vlaue;
    const nounInput = document.getElementById("nounInput").value;

    document.querySelector("span#person1a").innerText = person1Input;
    document.querySelector("span#person1b").innerText = person1Input;
    document.querySelector("span#person1c").innerText = person1Input;
    document.querySelector("span#person2a").innerText = person2Input;
    document.querySelector("span#person2b").innerText = person2Input;
    document.querySelector("span#animal").innerText = animalInput;
    document.querySelector("span#verb").innerText = verbInput;
    document.querySelector("span#noun").innerText = nounInput;
    document.querySelector("span#exclmation").innerText = exclamationInput;

    document.querySelector("div#story").removeAttribute("class");
  };
};

We add console.log("Script executing!"); to the second line of our script to confirm it's running. (We already know our script is executing — but this is a good way to demonstrate what console.log() does.)

Next, we put console.log("Submit form successfully reached."); inside our onsubmit event handler.

Save the script and refresh the page in the browser. Make sure the DevTools console pane is open. We'll see Script executing! as expected. Now let's try to submit the form — but pay very close attention to the console while you do.

You'll see that our second message very briefly logs to the console and then disappears. The gif below demonstrates this. So what exactly is happening?

This gif shows the second `console.log` message briefly appear and disappear.

This is a very common error, especially for beginners, and there are a couple of clues that show what's happening.

Whenever a result flashes across the screen — or the console like this — it suggests that the code is executing correctly but that the page is reloading.

Remember that the default behavior of a form submission event is to load a new page. That means that by default, the page will refresh unless we prevent that default with event.preventDefault().

There is another subtle but important clue that let's us know when we've forgotten to add event.preventDefault() to our code. Check the URL after you submit the form and you'll see a ? within the URL. The question mark ? indicates that we've made a GET request with a form. A GET requests means we're making a request to a server, and we'll learn more about this in the future. If we prevent the default behavior of the form, we won't make a GET request. We just stay on the page and no question mark ? is added to the URL.

Let's fix the issue:

js/scripts.js
window.onload = function() {
  console.log("Script executing!");
  let form = document.querySelector("form");
  form.onsubmit = function(event) {
    // we've added event.preventDefault(); below
    event.preventDefault();
    console.log("Submit form successfully reached.");
    const person1Input = document.getElementById("person1Input").value;
    const person2Input = document.getElementById("person2Input").value;
    const animalInput= document.getElementById("animalInput").value;
    const exclamationInput = document.getElementById("exclamationInput").value;
    const verbInput = document.getElementById("verbInput").vlaue;
    const nounInput = document.getElementById("nounInput").value;

    document.querySelector("span#person1a").innerText = person1Input;
    document.querySelector("span#person1b").innerText = person1Input;
    document.querySelector("span#person1c").innerText = person1Input;
    document.querySelector("span#person2a").innerText = person2Input;
    document.querySelector("span#person2b").innerText = person2Input;
    document.querySelector("span#animal").innerText = animalInput;
    document.querySelector("span#verb").innerText = verbInput;
    document.querySelector("span#noun").innerText = nounInput;
    document.querySelector("span#exclmation").innerText = exclamationInput;

    document.querySelector("div#story").removeAttribute("class");
  };
};

We've made one change to our code to fix the issue — we've added event.preventDefault() right inside of the onsubmit event handler. If the ? is still at the end of the URL, remove it and anything after it, and refresh the page. For example if you are serving the project with LiveServer, your URL might look like http://127.0.0.1:5501/mad-libs.html?person1Input=Mohammed, and you'll want to reset it to http://127.0.0.1:5501/mad-libs.html. If you forget to do this, there shouldn't be an issue, but you should know that your URL won't automatically reset with a page refresh.

Now try filling out the form. The text from our fantastical adventure will appear — and both messages will be properly logged to the console. Finally, check out the URL — a ? wasn't added.

If you ever find that a form submission isn't working correctly, checking the URL for a question mark is the first — and easiest — debugging step.

Finding the Second Error

As noted in the example above, console.log()s can be useful for seeing which code is reached. However, we can use console.log() for other bugs, too — including the next issue we are having with our Mad Libs story.

Here's how our story looks now (yours will look a little different depending on the words you input into your form):

"One day, Mohammed and Wei were walking through the woods, when suddenly a giant cat appeared. "woah", Mohammed cried. The two of them _________ as quickly possible, and when they were safe, Mohammed and Wei gave each other a giant banana."

We are getting some input but not all of it. Specifically, the verb isn't showing up. We can see that the underscore __________ is left in place. If the default value in the story isn't being updated for the verb, this already gives us an idea that there is something wrong in the code that displays the verb value. So, how can we use console.log() to help us out? We can log all of the verb-related values to the console and see what shows up as an issue. Check out the following updates to our scripts! Note — we've removed the console.log()s from the last error.

js/scripts.js
window.onload = function() {
  let form = document.querySelector("form");
  form.onsubmit = function(event) {
    event.preventDefault();
    const person1Input = document.getElementById("person1Input").value;
    const person2Input = document.getElementById("person2Input").value;
    const animalInput= document.getElementById("animalInput").value;
    const exclamationInput = document.getElementById("exclamationInput").value;
    const verbInput = document.getElementById("verbInput").value;
    // new line below
    console.log("verbInput = " + verbInput);
    const nounInput = document.getElementById("nounInput").value;

    document.querySelector("span#person1a").innerText = person1Input;
    document.querySelector("span#person1b").innerText = person1Input;
    document.querySelector("span#person1c").innerText = person1Input;
    document.querySelector("span#person2a").innerText = person2Input;
    document.querySelector("span#person2b").innerText = person2Input;
    document.querySelector("span#animal").innerText = animalInput;
    document.querySelector("span#verb").innerTex = verbInput;
    // new line below
    console.log("targeting span in story =", document.querySelector("span#verb").innerTex)
    document.querySelector("span#noun").innerText = nounInput;
    document.querySelector("span#exclamation").innerText = exclamationInput;

    document.querySelector("div#story").removeAttribute("class");
  };
};

We've added two console.log()s:

  • The first one is checking the verbInput variable we create to make sure that we're successfully getting the input value from the form.
  • The second one is checking that we've correctly targeted the <span>'s innerText property so that we can update our Mad Libs story with the verb: document.querySelector("span#verb").innerTex.

Notice that we've added variables and text as the argument to each console.log() method call. Here are the new console.log()s that we've added to our scripts:

console.log("verbInput = " + verbInput);
...
console.log("targeting span in story =", document.querySelector("span#verb").innerTex)

When we're working with multiple console.log()s it's helpful to include a descriptive message that distinguishes one from the other. We can combine text and variables using a plus sign + or a comma ,.

Let's submit our form again and see what we get.

This image shows the two messages logged from the `console.log()`s we added to our scripts.

Notice that for each console.log() there's scripts.js:14 and scripts.js:25 listed. This indicates the location of the console.log() in our code, including the file name and the line number.

As we can see from the image above, the second value of document.querySelector("span#verb").innerTex is listed as undefined! This means that there's something wrong with how we've targeted the <span> tag's innerText property. If we review this code, we should be able to spot that there's a typo: a missing t in the innerTex property.

Let's fix that in our code, save our scripts file, refresh our website, and resubmit our form. At this point, our website should be working correctly again.

Once we are done with our debugging, we always need to remove all console.log() statements from our code base. Why? Anyone can open the DevTools console and see messages that are logged there and it makes our webpage look unfinished. That's why it's considered bad practice to leave behind console.log()s from your debugging.

Summary


console.log can be a very useful tool, especially for beginning developers. We can use effectively in two cases:

  • To quickly check if code is being reached.
  • To see the value of a variable, just like we did above.

However, there are two things to consider about this tool. First, it's not as efficient as other debugging tools. It's definitely good to have in our toolbox, but usually it won't be the first tool we reach for. We'll learn about more sophisticated debugging techniques in upcoming lessons.

Second, once you are done debugging, you need to go back and remove console.log() statements from your code. They won't break anything but they make your finished code look sloppy. They are clear evidence of the debugging process — and should never be in portfolio-ready or production code. You will always be expected to remove any console.log() statements from your independent projects before they are submitted.

Debugging Using console.log()


  • console.log() allows us to log messages in the DevTools console. It can be helpful for making sure code is reached or checking the value of variables.

  • console is a Web API and log() is a method of the console object. This object has other methods and properties that you can explore on your own time.

  • Don't forget that the default behavior of a form submission event is to load a new page. We don't want to do that so we need to use event.preventDefault() to prevent that behavior.

  • We can tell that our application has attempted to make a GET request to a server and reload the page if a ? is added within the URL in our browser address bar.

  • When you use multiple console.log()s, you should add a description so they are easier to track in the DevTools console. You can chain text and variables together with + or ,. Here are two examples from the lesson:

    • console.log("verbInput = " + verbInput);
    • console.log("targeting span in story =", document.querySelector("span#verb").innerTex);
  • If you add console.log() statements directly to your code, make sure to remove them after you are done. Otherwise, your code will look sloppy.

  • While console.log() is a useful tool, don't overuse it. Adding breakpoints and other debugging tools are generally more effective. We'll learn about these in upcoming lessons.

Lesson 53 of 72
Last updated July 17, 2022