This course has been updated! We now recommend you take the Introduction to Dev Tools, v3 course.
Transcript from the "Step-Through Debugging" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Jon: That was the editing phase and now we're moving into the debugging phase over here which will be pretty fun. So step through debugging, which is a concept that is really popular in a lot of programming languages, but for a long time was missing as an option from JavaScript, so I think it's new for a lot of people.
[00:00:24] The basic idea is one of the probably the most common way I see people debug JavaScript applications right now is console log all over the place, right? It's probably what a lot of you do and something like going in each function console log, it worked, console log, it didn't work and then refresh and see what's in the console.
[00:00:40] So step through debugging allows you to have a lot more control than that and just be more precise in general. So let's kind of do one together, kind of talking it through, and then we'll have one more as a challenge where you can do on your own. So I'm gonna go to this Debugging tab.
[00:00:57] This will be the challenge, what's wrong with this Github thing. But in the meantime, I put another little file so I'm gonna open up the dev tools, I'm gonna go to Sources, make this a little bit bigger.
>> Jon: I'm gonna go ahead and remove this mapping for now, the workspace, cuz I don't need it any longer.
[00:01:18] And basically another cool little tip that you can do here, let me close these, is you can Cmd+P and you can do a fuzzy search just like Sublime or Atom or anything like that. So you can start looking for files this way. You can do .js to see the .js files, .css, anything like that.
[00:01:34] So I made this one which you wouldn't be able to find maybe naturally cuz it's just set aside but hopefully the GitHub one will be a little bit easier. So this is debugging2.js that we'll do together. So I'm gonna not serve in the file system this time. So basically I've got this code and it's a little bit confusing.
[00:01:54] It's functions that call each other whatever. And I wanted to show step through debugging so we can really get a feel for how this can help you better understand the code that you're working with. So, before we kind of squeeze this right panel off to the side and ignored it.
[00:02:07] Now we're gonna do the same thing with the left panel. So we don't need this kind of file system thing anymore, now we want these two. So the first thing that I'll do is I'm gonna go ahead and the way you add what's called a break point is by clicking on a line number.
[00:02:20] So, I'm gonna click on line number 2 and you get this blue breakpoint here. So, I'm not sure where everybody's at, as far as this goes. So, I'm kinda gonna start with an explanation from the beginning and move through it. So, basically the idea with step through debugging and a breakpoint and why those are named that way is a breakpoint is communicating with the browser and it's saying when you go to parse this code.
[00:02:42] I want you to halt all execution and I want you to maintain state of everything that you had going on at that point. And I want you to give me control. So we're actually really just pausing the JavaScript execution. And the reason it's called step through debugging is because from that pause, you're then able to either step into the function that's being called, step over it to the next one, or step out of it back.
[00:03:06] So you get these kind of three moves here. So let's take a look at them. So I set a breakpoint by clicking on a line number and then I'm gonna go ahead and just refresh the page. So it's gonna load all the HTML and CSS just like normal, and it's gonna load the JavaScript file just like normal.
[00:03:20] But now when it goes to parse it and run it. I should say not parse it. So you're not gonna hit a breakpoint just because the code exists. You're only gonna hit a breakpoint if that code actually goes to be executed. So if I didn't have this foo here where I'm calling a function, the breakpoint is not gonna show.
[00:03:40] Or it's not gonna pause. But since I call foo and it goes to execute this line, it pauses it here for me. So we get this little paused in debugger. Ignoring this tab over here, we've got a couple of things going on over here and this is where things start to get pretty technical.
[00:03:56] So stop me if I gloss over something or if I need to slow down or anything like that. So I'm gonna pretend this isn't here for now. So we've got [LAUGH] watch, Call Stack, and Breakpoints. So the breakpoint is just letting us know because often in more advanced applications, you'll have breakpoints all over your application, more than just one.
[00:04:17] So this down here, this section, we can kind of ignore because this is only gonna tell you where all your break points are. So let's kind of cut this whole section out, forget about it. Watch allows you to spy on any variable, anything declared. So for example, if we wanted to see what one is set to before this line gets executed.
[00:04:41] We can go ahead and add something to Watch and type in one and hit Enter and you'll see that it's undefined. However after this line is executed, if we keep one being watched, you'll see that it's set to the string one. So this is really cool. So you can even do things like you can double-click to edit, you could set it to foo, and it'll tell you that foo is a function, right?
[00:05:04] And then you can even dive down into it like this and see, does it have any arguments? No, what's its prototype? Things like that. So you get this full control where you can really get a good understanding of what's going on here. And then the call stack is just simply how did we get here?
[00:05:21] Why did we execute this bit of code? So for this case, this is contrived, an example. It's really, really simple, right? We called foo because foo was called by anonymous function here, right? We called foo so we got to foo. In a bigger code base, you're often going to see things like well, you had an event listener which went through jQuery.
[00:05:44] jQuery did the on-click and then jQuery called its trigger method and then jQuery trigger called this, you know what I mean. So you'll start seeing these call stacks that are longer and longer the more advanced your program is. For this example, it's really simple. So it's not uncommon to see 30 files in the call stack or something like that in a real application.
[00:06:04] So this is stuff that we're watching, this is all totally up to you to add and remove. And then this is like at whatever break point we're at, how did we get here? Those are kind of the two things going on and then very simply this will just pause wherever you tell it to.
[00:06:18] So you can do things like you can click back and forth in this call stack. If there were multiple files, it'll jump through those multiple files but since there's only one, it'll just jump from line 2 up here to line 27 down here. And so, okay, so now we're kinda here, we see that we have this function foo.
[00:06:34] We already checked one and it's undefined. So now we've got some choices and the choices are up here. So we can resume script execution, this for right now will just display the rest of the page because we don't have any other break points. But if we did have other break points, this is like, I didn't want this one, skip through for now.
[00:06:52] So this could be useful if you were checking when a function errors and you put a breakpoint in the function and the first time it hits, it's not the error. So you're like, just play on, just keep going. The second time it hits, it'll stop again. But since we only have this called once, hitting resume script execution will just resume the script as is.
[00:07:11] You can step over to the next function call. So okay, we stopped at one, that's great. Stop when anything else happens. Stop the next time a function's called and we'll do that in a second. You can step into a function call, so if the next place we stop was bar.
[00:07:28] And we didn't wanna skip all the way down to this call. We could actually start stepping inward. So if you think about like when you're writing JavaScript code, you kind of start building these pyramid sometimes of functions, right? So you've got your Ajax function and then inside that is a success function and then inside that, you're sorting names or something like that, right?
[00:07:46] So step into is just going one next function in. Basically kind of like looking for curly braces almost, and stepping in. Stepping over would be like if you have foo and you have bar. You're not gonna go into foo, you're just gonna step over to bar and stop at the next one.
[00:08:02] And then when you step in, you often need to just step back out. So that's really the only three ways that you can go. You can step over it, you can step into it, and if you've stepped in, then you get the option to step back out of it.
[00:08:14] So let's play with that, cuz that's kind of an advanced concept. Yeah, go ahead.
>> Speaker 2: Can you touch on that async check box up there?
>> Jon: Yeah, definitely. So basically, and this is really cool, a powerful feature. Basically the stack traces are typically reserved for these synchronous methods like what foo calls bar calls bad, something like that.
[00:08:38] Chrome dev tools is adding a lot of really cool support around async, promises, await, things like that. And so basically an async stack trace is like, if you had a file, script.js, and it did some Ajax thing and then came back with a success function and called something else.
[00:08:58] So it's basically just the full asynchronous stack trace. So if you're working with Ajax or something like that, you could have that ticked. If you just want to see what immediately called the function, then you don't have that ticked. Okay, cool, so the point being with these things is that I really want people to get comfortable clicking through them.
[00:09:18] Because I think a lot of people just don't use it cuz you get to a page like this, and it's just really intimidating looking. There's a lot going on. So you can't really mess anything up here. And worst case scenario, you just hit Cmd+R or Ctrl whatever Windows people use, and you just refresh the page and you'll get right back to this stack trace, this breakpoint.
[00:09:38] So you can really just play. So if I hit resume script execution, like I said, it's just done. There's no other breakpoints. So I'll hit Refresh again. And on this new Refresh, again, it pauses in debugger at line 2. So this time I'm not gonna hit Play. This time I'll hit step over to the next function call.
[00:09:54] So I hit step over and it goes for a little bit and it goes. So now this is important to notice and kind of cool. Some people might have thought that it would stop here, but this is just this function declaration, right? It's not actually executing any code.
[00:10:08] So this is actually gonna get hoisted, right, JavaScript hoisted to the top. So the next thing that actually executes is calling this function bar here. So let's say we want to step over again and see what happens next. It goes to foobar. So from bar, if we had stepped in, that would have meant going inside bar.
[00:10:28] But to step over, it means go to the next thing that gets called foobar. Does that make sense as I know it's like this took me forever to get my head around. I kept clicking on one when I meant the other one or something like that. So yeah, so then we can go into foobar and it's like okay, foobar I'm interested in stepping in cuz if I skip over foobar, it's done, right, there's no more code to execute.
[00:10:48] So I'll step into foobar and boom, get a breakpoint here at line 13, the beginning of foobar. So there's nothing to step into here, it's just an object creation. But you can start to really get a feel for, especially with JavaScript's rules around things like hoisting. It can be confusing to understand how your program is executing and step through debugging, even if you don't have a bug can be really useful for just understanding what lines get executed when, what stuff's being set.
[00:11:17] So for example, if we step back and back one more. And then, can I step into foo now? See, all right, even I screwed it up. So, if you step over, then stepping out is not gonna get you back. If you step over and you need to go back to something, you gotta restart the application process, basically.
[00:11:42] So, I'm just gonna go ahead an restart it here. So if I wanted to check on, I'm watching this variable one, and one is undefined here, right? Cuz it hasn't executed this line yet. But if I step to the next function call which is this bar here on line 8, you'll notice that the one that we're watching over here is set to this variable.
[00:12:01] So that's really cool. The other thing that I wanted to mention that's really useful is as state is preserved, you can also use the console as though the application were frozen in time. So if I go to console and I just type one, it actually knows my variable frozen in state, as set to this string of one.
[00:12:23] So you can kind of take things into the console and click through them or play with them, stuff like that.