Debugging Tips & Tricks: A Deep Dive into Console Log, Debugger, and Breakpoint Methods
Published: 2023-03-17 21:00:51

As a software engineer, debugging is a crucial part of the development process. For anyone new to coding, it becomes even more critical as part of the learning process. Debugging is the act of identifying and fixing errors in your code to ensure it runs smoothly. In Visual Studio Code (VSCode), there are several tools you can use to help you find that bug as you build out your code, and even build out your code more efficiently (possibly preventing bugs from ever surfacing). These methods include `console.log()`, `debugger`, and breakpoints. Having them in your back pocket and knowing when to utilize them will benefit you now and even more so down the line (in your application, and your career).

![Homer Simpson - bugs gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdgofvg3rq03fd3a6o4r.png)


## Console.log( )
The `console.log` statement is one of the simplest ways to debug your code. It allows you to log data to the console, where you can view it in the VSCode Debug Console or the console in your browser. This is particularly useful for logging values of variables and data structures to see what’s happening at different points in your code.

Think about making a fetch request. When you are requesting data from an external source, data that the entirety of your code is often built around, it’s worth it to ensure you are correctly fetching that data before actually building anything else out. The more code you write, the more lines there are to debug — so make sure it works before you get too far into the weeds. This is `console.log`’s moment to shine:

```
function getParks(parksUrl){
    fetch(parksUrl)
    .then(response => response.json())
    .then(parkArray => {
        console.log(parkArray)
    })
}
```

`console.log(parkArray)` renders the following data in the browser console:

![Rendered parkArray data in the browser console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ras7gv7228263s7ec9uo.png)

Look at that — an array of national parks! Confirming the fetch is successfully accessing `parkArray` with a quick `console.log()` provides confidence and confirms the fetch is working as planned.

`console.log()` quickly becomes your best friend when writing code that feels out of your element. Learning something new? Trying something you never thought you could do? Using a simple `console.log()` can confirm you’re on the right track before you proceed. I recently stepped out of my comfort zone and attempted what was originally defined as a stretch goal for a project: using a geocode API to take a user-entered location (city and state) to fetch data that contained the latitude and longitude for that location. The lat/long was needed to meet the requirements of another API used to render sunrise and sunset times. Asking someone for their latitude and longitude is not nearly as user-friendly as asking a user for their city and state. Not only did that seem like a hurdle on its own, but the user-entered information needed to be translated to a format that the API would accept.

```
fetch('https://maps.googleapis.com/maps/api/geocode/json?address=Mountain%20View%20CA&key=${apiKey}')
.then(response => response.json())
.then(console.log)

function testSplit() {
    const str = "Mountain View"
    const splitStr = str.split(' ')
    console.log(splitStr)
    const join = splitStr.join('%20')
    console.log(join)
}

testSplit()
```
As you can see from the code above, the initial `console.log` is rendering the fetched data and confirming the latitude and longitude is in fact being returned. A great place to start! The `testSplit` function is then breaking down the steps needed to take the user-entered city (with an added level of complexity due to the possibility of a city containing two or more separate words, like Mountain View), creating an array of separate strings, console logging that `splitStr` variable to ensure it’s what’s expected, then joining the strings with a value of ‘%20’ (since that is how the API will accept the location). `console.log(join)` returns a value in the console of ‘Mountain%20View,’ confirming everything is working as planned. Isolate steps, build small, breathe, test, celebrate, and code on! You can see below how the described `console.log`s read in the browser console — first the array of strings, then the values joined by ‘%20,’ and finally, the response from the test fetch containing the latitude and longitude of Mountain View, California in purple:

![Confirming test data in the browser console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zilcejhf03jzbhcbrjvv.png)


## Debugger
The `debugger` keyword is another simple way to debug your code and a great tool to have on hand. It’s used to pause execution of your code, so you can inspect the values of variables and the state of the program at that point. This can be especially useful when you need to step through your code one line at a time.

Why would you need to step through your code line by line? There are many reasons, but form submissions are the first thing that come to mind. While the purpose of a form submission can vary wildly, regardless of what it is being used for, that user-entered data needs to be grabbed from the form to do its job. One key aspect of debugging form inputs is making sure that the input values are being correctly passed from the form to the code. A `debugger` is the perfect tool to stop the execution of the code to play with each input from the form, inching yourself closer to functioning code. Let’s check it out, building off our test code from above:

```
sunForm.addEventListener('submit', (e) => {
    e.preventDefault()
    debugger
    const location = 
    const image = 
    const city = 
    const state = 
})
```
Adding the `debugger` keyword to the form code will pause the execution of the code when the form is submitted. Here, our goal is to find the exact values for the user-entered data of location, image, city, and state in our form before adding them to the code. Not let’s see the `debugger` live in action:

![gif of using debugger live in the browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nsmqydl12nzq4ju5r1qc.png)

Above, `debugger` allowed us to pinpoint the form, the specific input, and eventually, the exact value of the form input to guarantee the code we are using is correct. Thinking you could do `e.target.location.value` makes sense since that input is designated for ‘location’ information, but it actually throws an error — ‘cannot read properties of undefined (reading value)’. Following that thought blindly and running with it is basically just building out non-functioning code from the start. `debugger` allows us to correct the issue before it is ever really an issue and nail down the appropriate value to build on moving forward. After using the `debugger` and console.log methods to help us get there (and to continue to check along the way), the completed code is as follows:

```
sunForm.addEventListener('submit', (e) => {
    e.preventDefault()
    debugger
    const location = e.target[1].value
    const image = e.target[0].value
    const city = e.target[2].value
    const state = e.target[3].value
    const cityJoin = city.split(' ').join('%20');
    console.log(cityJoin)
    const stateJoin = state.split(' ').join('%20');
    console.log(stateJoin)
    const finalJoin = `${cityJoin}%20${stateJoin}`;
    console.log(finalJoin);
    fetch(`https://maps.googleapis.com/maps/api/geocode/json?address=${finalJoin}&key=${apiKey}`)
    .then(response => response.json())
    .then((data) => {
        const lat = data.results[0].geometry.location.lat;
        const long = data.results[0].geometry.location.lng;
        const tmz = e.target[4].value;
        const newCardObj = {
            image,
            location,
            lat,
            long,
            tmz,
            city,
            state,
            likes: 1
        }
        getAllSunrises(lat, long, tmz, newCardObj)
    })
    sunForm.reset()
})
```


## Breakpoints
Breakpoints are another useful tool for debugging your code. Once set, the execution is the same as using the `debugger` method detailed above. The only difference is how the breakpoint is established.

Breakpoints do not require a keyword to be added to the code. Instead, to add a breakpoint in VSCode, simply click in the gutter (the area to the left of the code editor) on the line where you want to add a breakpoint. Once added, a breakpoint will pause execution at that line, and you’ll be able to inspect the state of the program and the values of variables in the console, just as with the `debugger` method (note: in order for your breakpoints in VSCode to stop the code execution in the browser, you need to an install a debugger extension for your preferred browser).


![Example of setting breakpoints in VSCode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5385dp92q5xed3y1y7c.png)

If you lost interest at new extension but you still want to reap the benefits of a breakpoint, you’re in luck! Breakpoints can be set in your browser’s developer tools directly, without the use of an extension. Simply open Sources in the dev tools and click on the line of code where you’d like a breakpoint set. Using the same example as before but implementing it with the browser’s breakpoints would look like this:


![Example of setting breakpoints in chrome Dev Tools in the browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dkxzu35qn544ffv1wmfr.png)

By adding breakpoints on the lines for the form inputs , you’ll be able to inspect the values of location, image, city, and state in the console before the rest of the code runs.

You may notice if you’ve ever right-mouse clicked on a breakpoint that they can be edited. In doing so, you can set a _conditional_ breakpoint — another powerful tool in the debugging arsenal of a software engineer. They allow you to set a breakpoint that only triggers when a specific condition is met. This can save time and effort by reducing the number of times the debugger needs to be invoked and by allowing you to focus on specific parts of your code.

To set a conditional breakpoint, right-click on the line number where you want to set the breakpoint, or on an already established breakpoint, and select “Add Conditional Breakpoint”. You will then be prompted to enter a condition that must be met before the breakpoint is triggered. The condition is expressed in JavaScript and can be any valid expression that returns a Boolean value.

Conditional breakpoints are best used when you need to debug a specific case or scenario that only occurs under certain conditions. For example, you might set a conditional breakpoint on a line of code that performs a complex calculation, but only trigger the breakpoint when a certain variable holds a specific value. This way, you can debug the calculation only in the cases that you’re interested in, without having to step through the code each time.


## Does Language Matter?
The basic debugging methods in VSCode, such as console log, breakpoints, and user `debugger`, are language agnostic and can be used with any programming language. However, some programming languages may have unique debugging features or extensions that are specific to that language, and are not available for other languages.

For example, the Python extension for VSCode provides advanced debugging capabilities such as multi-threaded debugging, debugging of Jupyter notebooks, and debugging with the Django web framework. The Node.js extension provides debugging support for Node.js applications, including the ability to set breakpoints in server-side code and inspect variables on the fly.

So, while the basic debugging methods are the same across different programming languages, it’s worth checking to see if there are specific extensions or features available for your language of choice in VSCode.


## Conclusion
In conclusion, `console.log()`, `debugger`, and breakpoints are all useful tools and a great place to start for debugging your code in VSCode. They allow you to log data, pause execution, and inspect the state of the program at specific points in your code, making it easier to identify and fix errors. Using these tools as you build applications also ensures you are writing your code correctly, helping you avoid possible bugs at a later point. Practice them even when you don’t need to as a way to double-check your understanding of not only your code, but also the functionality of the method. That way, you know how to debug properly when you need it most. With these tools in hand, you can be more confident that your code is running smoothly and focus on creating the best user experience possible.