This course has been updated! We now recommend you take the Introduction to Dev Tools, v3 course.
Transcript from the "Step Through Debugging" Lesson
>> Jon Kuperman: So now that is done, the rest of the exercises should be a lot more fun cuz we won't have to install anything else. So the next section that we're gonna be moving into is Debugging. So we kind of walked through how we would go about authoring new code or changing existing code from the DevTools.
[00:00:17] And now, we're gonna kinda pivot a bit and talk about an app that we finished, but there's a problem with that and we really wanna figure out why some errors are occurring or why some bug is happening. And so for this one if we pop back over to the DevTools and go to this debugging tab.
[00:00:35] So the DevTools provide the step through debugger, which, if you're coming from other programming languages, like back end languages, might be a really familiar concept to you. But if you're new to development or if you've only been doing web development, it might be a less familiar concept. So if I go ahead and open up the DevTools again, and let me close all of these.
>> Jon Kuperman: And then I'm gonna open a new file. Remember, I said I was gonna sprinkle some tips and tricks in here. One cool thing is if you hit Cmd+Shift+P or Ctrl+Shift+P on Windows. You get these like auto complete where you can do anything that you can do with the mouse in the DevTools.
[00:01:15] So I can hop over to the Elements panel and it moves me, Cmd+Shift+P, hop over to Sources. And it moves me Cmd+Shift+P, there's tons of cool stuff you can do here. So yeah, I use that pretty often so I don't have to hop back over to my mouse.
[00:01:29] So yeah, so I'll open my sources, and then instead of that Cmd+Shift+P, which is how to hop around within sources, you can Cmd+P. And that's gonna be like if you use sublime Cmd+T as your fuzzy search through your file system or a lot of other editors, it'll be like Cmd+P or maybe Cmd+Shift+P, whatever.
[00:01:45] So this is gonna be your fuzzy search. So it's gonna search through all of the files that it has access to. And one way that we might wanna simplify this now that we're not doing work spaces anymore is to go ahead from file system and just remove this work space so there's less kinda clutter, there's less stuff to get in the way.
[00:02:01] So if I hit Cmd+P, I can kinda see like all the files that are coming down on this page, right? So I can see my debugging, some css files, this Chrome extension which I meant to turn off. JQuery, Lodash, all these things are coming down. And so if I go ahead and I open the debugging file which is here.
[00:02:46] Just kind of some straight forward a few functions calling each other. You can imagine your production code is gonna be a lot more complicated but for the example I think this will be good. Another thing that I wanted to point out, we'll cover in a minute, this concept of setting breakpoints, right?
[00:03:00] And so setting a breakpoint is to say, as soon as the parser hits this line of code, pause and show me what's going on, what the state of the world is out there. But there's another cool way you can do it, which is this debugger keyword. And so you can put the debugger keyword in your actual code and then refresh the page with the DevTools open, and it'll have a breakpoint there.
[00:03:19] The danger here is you can ship this to production, right? And then, anybody with DevTools open is gonna get this breakpoint every time they go. So if you're gonna start using debugger, you probably want a lint rule to make sure you don't push the debugger to production, same with probably console logs, or alerts, or anything like that.
[00:03:36] So if we go in my editor.
>> Jon Kuperman: And lesson-debugging. We can see I have this debugger word in here. So before I've done anything with the DevTools, just by virtue of having them open, if I refresh the page, we're gonna get this paused in debugger, right? That's because I have the DevTools open, and I hit a website that has the debugger keyword in it.
[00:03:57] So it stops me here. So a few things like to do the editing section we use the left tab a lot, right? That's how we added workspaces or checked out files. For the debugging section I'm gonna kinda minimize them and then move it over to the side a little bit, because we're not gonna be using it as much.
[00:04:11] We are gonna be using this right tab a lot more. So you'll notice a few things happen when a breakpoint is triggered, and just for an example say this debugger is the exact equivalent, if I go back to my code, remove the debugger line and save it. And then I can click on any line number, and any line number that is actionable will give me this little blue thing, that means there is a breakpoint there.
[00:04:35] So now there is a breakpoint here when you refresh it stops here as well. So you've kind of got two different approaches for how to get a breakpoint. You can do it in the code or the word debugger or if you know where the code is in sources you can click on that line number and it will pause execution there.
[00:04:47] So when that happens you can get this little message here. Pause it on breakpoint and you get a couple of different things over on this right side. In the middle here, we can see exactly what we'd expect, we see our source code, and the line that's highlighted blue is the line that we're paused on.
[00:05:02] So if you had multiple debuggers it'll always highlight blue the one that it's actively stopped on. I'm gonna expand this little right side here a little bit. So we've got some options that we're gonna cover. At the very top here we have our kind of navigation options. We'll cover these in a minute but the basic idea is once stopped you have some choices.
[00:05:20] You can step over, step into, step out of or see the next one. And we'll cover what each of those mean by the kinda concept is where it stop to a certain line of code and it's like whoa, did you want it? And maybe it calls a function, it's like, do you wanna go into that function or do you wanna go to the next line of code or do you wanna, you know.
[00:05:36] And then when you go into the function it's like okay, I'm done here, I wanna go back out. You can kind of move around like this. The big thing to keep in mind is you can't go backwards, right? It's not a time travelling debugger, like if you use something like Redux DevTools, that's a time travelling debugger.
[00:05:50] So you can replay actions or you can undo actions, this isn't like that, this is just unidirectional as it's parsing. So if you step into a function and then step back out of it, you don't go back to where you were, you go to the next line now.
[00:06:02] But, either way, you've got something paused and you can kinda play around. So we'll cover this in-depth in a second here. We got a few things here. So if I minimize all these, we've got a lot of different things going on. So watch is really useful. Let me delete these, what watch lets you do is it lets you put in any expression, so it could be a variable, it could be multiple variables, anything like that.
[00:06:27] And what it'll do like if I go add and I add one here, it'll tell you if that variable is defined in the current scope what it's set to. So we can see one is defined, it's a function. If I click on it it shows me the arguments the caller the length.
[00:06:41] So this is a really useful like if you're doing an API call and there's an error and you're not sure what the error is, you can put a debug statement in the success function. And then you can click Watch, add input your data name, whatever variable your name it.
[00:06:55] And now you can start really clicking through with no worry about time, things or frozen you can click through. So that's the Watch is good for. It's also cool, because anything that you add the Watch, it'll keep trying to evaluate. So if I were, example, to declare a variable in a function and put a breakpoint there and put a watch on it, we're good, right?
[00:07:14] We're gonna see the variable. And then let's say, I go step over and then move into another function where that variable no longer exists. The Watch will update in real time and say okay, well, now it's undefined. And if you go back and say okay, now it's the variable.
[00:07:27] And so it kinda tells you what's available at that time, which is really handy. The Call Stack It's really simply like how did we get here, right? So it's like whenever you put a debugger, it's like how did we get here? So the Call Stack get really big in production apps as you can imagine.
[00:07:41] But the kind of important thing is if you're seeing a line of code like an error condition is getting hit and you're like well, why is the error condition getting hit? You'll see this big call stack here. So I can see here one got called, it's like well why did one get called?
[00:07:56] It's like, because of this anonymous function. So I can actually see the call sign where the function was invoked, right? With a bigger app, or whatever, if you're in the error condition see what, if, check for the error condition, you can step back as far as you want.
[00:08:08] You'll normally see at the very bottom of a call stack you'll see a global function call, like this. Maybe you'll see an event happen, like a browser event, like a click. How did we get into this area, it's like well, somebody clicked. Or you'll see like an async, like a fetch call happen, those kinda things.
[00:08:22] So it starts at the very beginning, and it'll take you all the way through until that exact line of code. Scope is pretty handy, I usually just use watch. But you can see, I don't know if anybody is ever been like, you're trying to do like this.foo, and it's like, foo is undefined, or whatever.
[00:08:39] And you're like, what? Why don't I have access to it? So you can go into the scope and you can see exactly what you have access to at that moment in time, right? You can see, in the global scope, here are the things that we have access to.
[00:09:03] And you'll be like, it has foo and it has var, those kinda things. There's a lot of noise in here. So typically that's why I prefer to just add what I want via watch, right? So a watch for this.foo, and if it's undefined, then I'll change my watch to just be this and I'll see what's on there.
[00:09:19] The next one is just breakpoints. So this is just, as you start debugging this way, you might add more and more breakpoints. It's like okay, I want one here, and I want one here, and I like my one up here. So you'll add more and more. You can delete them by right clicking on one.
[00:09:34] And again you can remove all, or deactivate them, or whatever. You can also just uncheck them, which keeps them stored, kind a like cached, but they won't trigger any longer. So you can see when I uncheck this one, it goes from a dark blue to a light blue, light blue means deactivated.
[00:09:48] So yes, you've got kind of all these breakpoints all over the place. The bottom four, we're gonna get into later this lesson, but later, but I just kinda wanted to like walk through what's going on up here. So I would really say if you're trying to explore, that's awesome, you should look through all of it.
[00:10:02] If you're really just trying to kinda simplify things for yourself, you don't really need to look at the Breakpoints tab, cuz you can see them here. You should have your Watch open all the time so you can change what you're looking for, and you should have your Call Stack open all the time, so you can see how you got there.
[00:10:15] Those are the two that I use the most probably why they're at the top. Okay, so going back to this kind of concept of, is that kind of good for everybody? Just like what these panels kinda contain and why they might be useful. Okay, let me know at anytime if you have questions.
[00:10:30] I know there's a lot getting covered. So if we go all the way back to this concept where I just have one breakpoint at this one console log, that's all I've got. So as we start kinda wanting to navigate around you've got these five buttons here. So one of them is resume script execution.
[00:10:48] And what this one is gonna do is be like I don't need this breakpoint right now. Please continue going until either you hit another breakpoint or the page just loads. So since I only have the one breakpoint, if I were to hit resume script execution it'll just load the page, right?
[00:11:02] So hit that, it just loads the page. There's no more stuff to stop. If I had two breakpoints, like one here and one here, and I refreshed the page and I get stopped on this one. And I'm like, I don't really care about that right now. And I hit Resume, it'll just play to the next breakpoint.
[00:11:15] So resume is like cool, I'm done with this breakpoint, please move on until either you finish or you hit the next one. So I'll remove the breakpoint and I'll kind of refresh the page. So the next thing that you can do is that you can step over the next function call.
[00:11:29] So if you're at, let this one doesn't make a lot of sense till we hit this next one. So I'll hit step over and boom it moves me down to line two. So notice, things are changing a little bit here where we didn't manually add a breakpoint to line two, we only added it to this console log, and then we're now we are like stepping through the code, right?
[00:11:45] That's why I stepped through debugger. So we've stepped into line two, and now we got some choices, right? We can say like, I don't care about two, show me the next line of code. Or we can say I do care about two, go into that function, I wanna drill in and see what's going on.
[00:12:00] We don't really have the option to step out of the function because that'll just go back to the global, right? That'll just take us back out and we'll be done. So if we wanted to step in to two, we can click step into next function call and we'll see that the now the break point gets moved into this function two here, console.log from function two.
[00:12:19] So now again kinda the options are we can keep going, scripts done, right? There's no more breakpoints. We can not really step into anything because there's no more functions that we're calling, right? We can step back out and here's where I find like a lot of confusion I think to a lot of people, they would think, well, I was on line three, I stepped in to line eight, now, I'd like to step back out to line three again.
[00:12:42] But that's not exactly how it works. So if we step out, we'll notice it's completed with this line three and has moved onto the next line basically. And the reason again, it's not time traveling, right? In order to step into the function, it actually plays that bit of code.
[00:12:55] So when you step back out, it won't take you back in time. It'll just take you to what would of been next otherwise. So if that's confusing, if it helps to think about it. So if we start over again by refreshing and we hit Step Over. So we're here now, at this point, it would be equivalent to step over to and to step in to and out of, those are equivalent things, right?
[00:13:15] Stepping over a function is the equivalent of stepping into it and back out. I hope that's gonna high, think about it if that helps. So let's step over into three, get the same kind of option. Step into three, and where here, will step on to the next one which is four, we'll step into four, which is here.
[00:13:32] This one really just kinda comes with the time, as you're kind of clicking around. The cool thing is it's a website, if you go too far, just refresh, okay? [LAUGH] And then you start back at the top again, no problems, pretty easy there. But I think we have an exercise on this coming up, and I think it just helps to even just do this on your own sites, like add a breakpoint, start stepping through until it gets really comfortable.
[00:13:52] Is everybody good so far? Yeah, a question.
>> Speaker 2: Who did that new step?
>> Jon Kuperman: What was that? I'm sorry.
>> Speaker 2: Is that a new option for just plain step after step out?
>> Jon Kuperman: Yeah, so this is a new option. So instead of stepping, it's a little bit weird, right?
[00:14:10] Because they do basically the equivalent thing. It is a new option, it's just a single step. So what it means is step is either over if it's not a function, or into if it is a function. So do the next thing is what step means, right? So when we're here and then we're like, okay, we hit step, it's gonna be like, is that a function that I can call?
[00:14:32] No, then I'll just step over, right? But now we're here, and we hit step, it's like, is it a function that I can call? Yes, so it will step in. Does that make sense? It's kinda like just do whatever is next, as opposed to you dictating whether you go in or over.
[00:14:47] And it kind of shows that like going in is not always an option, right? So for here, I went on console.log, and we say step in, it's not gonna do that, it's gonna be the equivalent. That's a little bit tricky, it'd be probably better if the buttons were disabled, is what it probably should be, right?
[00:15:02] Because you can't step into something that's not a function. They kind of all have their place, I think it's better in more complicated code where like calling things that are variables and you're like just do the next step basically.
>> Speaker 2: Thank you.
>> Jon Kuperman: Yeah?
>> Speaker 2: We were asking about those two arrows on the right of the right point?
>> Jon Kuperman: The two.
>> Speaker 2: So line number two, you've got a breakpoint on the left, and then there's.
>> Jon Kuperman: Yep, yeah, so this is really cool. We're gonna get into this a cool amount later. But DevTools starts adding all of, this like a lot of it's new, and it's really helpful.
[00:15:34] So what we'll start noticing, especially when you start debugging complicated applications, is as you set these breakpoints, instead of making you add watches for everything, it tries to be really helpful and just inline a bunch of contextual information for you. So I think I'm, let me try this, I think this might be a cool example.
[00:15:54] So instead of just calling one, I call one and pass in the word foo. And then over here I take the word foo and then maybe I console.log(foo), something like that. So we kinda refresh here. We can see that it inlines this information for me. So it's like showing me inline what got passed into the function.
[00:16:14] So I don't have to manually add watches. Similarly, it'll add these little arrows, anywhere where it has dropdown information, more contextual information. So it has two different things. It has contextual information on the console object, so I can hover over that and it'll show me what I can call on console, which is really great.
[00:16:32] And it also has information on this log function. And so I can hover over that and see that log is a function that doesn't take any parameters, mandatory.