Basics of Programming with JavaScript
-
Introduction to Programming -
Our goal now is to jump right in, and where we're going to start is Chapter 1 of the Up & Going book. So if you want to follow along, again YouDon'tKnowJS.com gets you to the repo, and if you want to follow along with us, essentially we're going to start from Chapter 1. I'm not going to read word for word the book to you, but I'm going to try to distill the same concepts that we deal with in the book. We'll try to go through those things. We'll take plenty of little mini breaks. After we've dealt with a concept or two, we'll take little breaks, and we'll have some time for you to practice these things. There is no substitute for you typing this in yourself either in your own code editor or in the dev console of your browser. Trying each one of these things yourself is really important. And that's true even if you already come to the table with experience. Don't just forsake the thing and say oh, I get that. Definitely I encourage you to follow along and participate. So, we start this book series, the Up & Going book is conceptually the first book of the series. This is the place to start, and it makes most sense to start from literally the very beginning. So, for those of you that don't really have a lot of programming experience, let me try to dispel a couple of myths and fill in a couple of details that you may not have heard before. So when people talk about programming, when they talk about writing code, essentially what they're talking about is typing into a text file, and that text file is referred to as your source code. Now the source code is a set of special words and phrases and operators, which are special characters. They're designed to give instructions to the computer on what to do. But the symbols and words and phrases that you put into that program are not actually in a form that the computer can directly understand. It needs some assistance. And so there is a step after you write these instructions into a text file, there's a step that comes along, and it goes by different names depending on the context that you're in, but there's a step that essentially comes along and converts the physical words, the readable code, as we would say, that you've written into a series of instructions that the computer can actually understand, and those instructions are in the form of binary, the 1s and 0s strung together. So, the first observation that I would make, and I think this is an important one regardless of what level of your experience in programming, is that the source code that you write is not really for the computer. It's almost sort of a side artifact of what the computer really cares about. There's a special program on your computer, a compiler or an interpreter or something like that that does care. But the overall computer system doesn't care about the source code, and it is actually possible to write a potentially infinite different set of source code files that when boiled down to those 1s and 0s would produce exactly the same stream of 1s and 0s. So if you could literally write an infinite number of different programs that do the same thing for your computer, then what difference does it make what source code we write? And that's the first big observation that I'd like to make is that the difference is that source code is not for the computer. I mean yes it's used by your compiler, but it's not for the computer. It is for the developer. It is for you to be able to look at what you've done and understand what your program is intending to do, and it is also for other developers, people on your team, your future self if you come back six months later and you're looking at a program. You want to write the code in such a way that it not only does the correct thing, but it also makes sense. That's an often overlooked topic. In fact, many times people come back after having written a completely nonsensical program and try to sprinkle in bits of sensibility to it. And I would encourage you to try to strive to go in the opposite direction. Try to write everything that you write in such a way that your future self, having no context and having completely forgotten, having had many margaritas and many nights of sleep since, that you could go back and look at that line of code and understand what it meant. What was it intending to do? What was its pros and its cons? Don't assume --- if you think, oh I know this variable can only ever have numbers in it, but if that's not obvious from the line of code, then that's an assumption that you've made that isn't obvious in the code and won't be obvious to another developer and won't be obvious to your future self. So it's incredibly important to approach writing source code from the perspective of the developer, more so even than the perspective of the program. Of course, you have to write syntactically correct code. You have to write code that works the way the language expects, and we'll spend plenty of time talking about that in a moment, but I did not want to gloss over the fact that the source code that you write is for developers. And there are lots of different things that you can do, and it will be an ongoing process. You will never completely master the skill of writing sensible programs. You can master the skill of writing functional programs with given enough practice. There's that old idiom, like 10,000 hours of practice makes you an expert or whatever. I don't even know if that's true. But if it were true in some respect to programming, it's possible to achieve a mastery over the JavaScript programming language. I do not think it's possible to achieve a mastery over writing sensible code in JavaScript or any other language. It is something you have to work at. It's something you have to try, you have to practice, you have to learn over periods of time. And I consider myself particularly not good at this. Most of my effort in teaching is not writing code, but writing code that's more teachable. And I struggle with that, to be completely honest. I struggle to figure out how can I rearrange this in a way, it's not just about what I call something, but how can I rearrange this in a way that actually makes sense to people, that fits the way our brains kind of try to linearly process through stuff? That's a difficult process, so it's not something I can just teach you as a rote skill and then you can be certified in it, but it's something I would encourage you to not gloss over. It's something that's very important to try to do. So, I already have started to skip over some things, so let's fill in some gaps. When we talk about writing source code, there's a word that's referred to, which is syntax. And in more formal terms there are a set of rules that put that syntax together, and that set of rules is called the grammar. So the syntax and the grammar together fit together as how to write a JavaScript program. It will tell you what are the valid combinations of characters, the valid combinations of words that you can put together to do what you want to do with your program. So the syntax of a programming language is much like the syntax for English or whatever your native tongue may be. There are actual physical things that you can do. There are punctuation marks in the English language, like the comma and the period and the exclamation mark. There are parts of phrases that work together, like a word used as a verb versus a word used as a noun. Those are things, but the way you put those things together into a phrase and then put phrases together and make a sentence, that's called grammar. And you maybe remember back in school you learned English grammar or whatever. So, there's a very similar concept in programming, learning first the syntax and then the rules of how to put the syntax together to make a coherent, what we call statement. That's what we call grammar. So, I will put the word grammar and the word syntax together from here on out, and I'll just use the word syntax. Most people do. But just so you understand, they're two different faces of the Rubik's cube, if you will. They're different parts of the same thing.
-
Statements -
A statement. What does that even mean? Well, a statement is a coherent set of those words and symbols that go together to express a single idea, a single instruction, if you will. Although statements can definitely be compound, just like most of my sentences are quite compound, statements can be compound, and they can perform more than one task, but typically there's a roughly one-to- one match between a statement and a concept of what you want to do. So, if I look at this very first statement that we see here, the a = b * 2, what I'll do is I'll try to take these things from the book, and I'll try to expound upon them here in my code editor so it's a little bit easier to read. So if we have a = b * 2, this is a single statement. In JavaScript, we recognize a single statement most typically by the fact that it ends with this semicolon character. Essentially, the semicolon is kind like a period at the end of an English sentence. It's like, I'm done. I've made that sentence, and I'm done; going to go onto the next sentence. Not all statements require a semicolon. There will be certain forms of statements that won't have an ending semicolon, although you can put them there. There are very few places that you could not put a semicolon, but there are places where they're not required. In fact, there are an awful lot of places where they're not technically required, and some people like to leave out semicolons in all of these places and assume. And you could do the same thing in the English language. A lot of people do on Twitter. They write entire sentences and paragraphs worth of content with no punctuation, no space, whatever, the hashtag sentences that you've seen where we have no punctuation or spaces. You can do that and probably still get the point across, but I would encourage you as starting out to be a bit more formal about it, so put your semicolons in in the places where it makes sense to end that concept or that task. Here what we're doing is saying I want to do a mathematic operation, so there's an assignment, there's a math statement that's happening. Let's break that down. What does that mean? Well, I see the number 2. That's a literal value. It doesn't need to be interpreted in any way, shape, or form. We just know it to be a value, and its intrinsic value is what we'd make sense. It is the mathematic number 2. We see that little asterisk symbol to the left of it, and the asterisk symbol is the multiplication operator in most languages, including JavaScript. And then to the left of that we see the b variable. Now you notice I'm going in right to left fashion, and there's a slight reason why I'm doing that, which is nuance, but we'll come back to that in a moment. But there's a b character there, and what does that signify? Well, if it's not otherwise a special recognized word, which we will call those keywords, by the way, keywords being the special recognized things that a language says. So, for example, for, F-O-R, or function, F-U-N-C-T-I-O-N, those are what we call keywords, and they're words that have special meanings to the language. But the b character has no special meaning to this JavaScript language. So if it doesn't have a special meaning, but it still looks like a word, then it's a variable. It's called an identifier. And in this case, when an identifier is used in that position as it is, it's representing. It's a symbolic representation of something that holds a value. Now, in our program we don't see what value it has, so this isn't a complete program because the b variable would've had to have been given some value for this to make any sense. Let's pretend for the moment that the b variable has the value 21 already in it. So what this statement says is go find that b variable, and the rules of how we find that are scope, and we'll come back to those later, but go find that variable and ask for what its value is, and pull that value out. So if we get the value 21 out, multiply that by 2, and we'd get, of course, the value 42, that special meaning of life value. I use that in most of my examples just to be silly. But what we've done is we've computed something on what we'd call the right-hand side. Hopefully I don't have to remind you --- if you're having trouble with left and right, you remember just hold up your left hand, and make an L, and that's your left, right? So, left and right. I'm sorry, I'm silly because I have a four-year-old son and a two-year-old daughter, and we're teaching them things like left and right. But on the right-hand side obviously there's b * 2. So that b * 2, that's an expression we'll come back to in a moment. And then on the left-hand side we have another variable called a. And in between the two we have an equals statement, and that equals statement is a special kind of operator that means assignment. So essentially what we're doing is we're taking everything on the right-hand side, computing its final value, whatever that may be, and then putting that final value into the thing on the left-hand side. You can think about this as right-hand side is the source value, and the left-hand side is the assignment; it's the target value. It's the target location, if you will. So what I'm saying is compute the value on the right-hand side, which we said would be the value 42, and assign it into the variable a. You can see why this together it has several different little pieces that we had to parse out what are these things doing, but as a coherent grouping of things, this is called a statement, and what we've done is compute the value 42 an assignment, so we would actually call this an assignment statement. Somebody says in the chat room, wow, the very beginning. Yep, told you. Very beginning, no experience. If we lose you, or if we bore you, just hang on because I promise we'll get further into stuff. So, that's an assignment. Statement.
-
Expressions -
Now, statements are comprised of phrases like they are in English, and these phrases are what we call expressions. So going back to this a = b * 2, there are essentially several expressions going on. The first expression is that literal value. A literal value expressed is a literal value expression, okay? And then there's an identifier expression, which is the character b. And then we take b * 2, we put those things together, there's an operator in between and two things on either side, and that is called an arithmetic expression, in this case a multiplication expression. So you can see there was an inner expression, an outer expression. And I could sort of make that more obvious if I use the parenthesis as sort of a grouping thing, so I'm going to use parenthesis to illustrate this idea of where the expressions are. So, there is an expression here, the parenthesis wrapping around 2; there's an expression here, the parenthesis wrapping around b; there's another set of parenthesis that wrap around this expression, which is a mathematic and arithmetic expression, a multiplication expression; and there's one more expression, which is called an assignment expression. So, all of this stuff, you notice I did not include the semicolon, all of that stuff is both an expression and a statement. It's an expression from here to here, and then it's the last thing to go out. There's nothing else outside of it, so it's also a statement. Does that make sense? There's an expression, an expression, an expression, and finally we get to what we call an expression statement where they become one and the same. So this grouping can kind of help you visualize where those things are, and that's actually a good practice, so that's the first thing that we'll try to do. I'm going to write a slightly more complex statement, and don't let it intimidate you if you're just starting out programming, but just from the perspective of trying to get your feet wet with understanding the difference between statements and expressions, kind of like when your English teacher had you go up on the board and underline all the verbs and circle all the nouns or whatever, I'm going to have you do that with this. I'm going to write a slightly more complex statement. I'm literally just going to make it up on the fly, so it might make no sense at all, but I'm going to write a statement, and then I want you to take that same statement and put in those parentheses like I just did identifying all the different places that there are expressions. So, let me just start out by saying something like a is equal to b * 2 +. Then I'm going to make a function call, which you haven't seen those before. And then I'm going to pass in an argument, c * 3. And there's my statement. So, copy that down first. You can copy this into your own code editor. You can type it into your console or something like that. It's a nonsense statement because we haven't assigned values to foo, b, and c yet. But just from the perspective of finding those expressions, go in and put your parentheses, or brackets, or whatever if you want, but take just a moment and try to find all the different places where there are expressions, and then we'll come back and solidify that. Alright, so, hopefully you had a chance to try your hand at that. Let's see how you did. So I'm going to walk through from the smallest to the sort of outer and identify all those different places that are expressions that make up this statement. So, because I already have a set of parenthesis in here that means syntax, I'm actually going to use brackets instead of parentheses, the square brackets, but conceptually again we're not doing anything syntactic. What we're doing here is just identifying visually, so I'm going to put square brackets around all of our expressions. So here we know that we have an expression for the literal value 3. I'm not making that an array 3. I'm just identifying that thing as a 3. We also have another expression, the value 2, and we have another expression for b, and we have another expression for a. I think in my previous example I forgot to indicate that the left-hand side is also its own expression, so the left-hand side is an expression. The c is an expression. The foo, of course, is an expression. So all of those are sort of our first level expressions. Now let's start doing some grouping of stuff. We know that the c * 3 is an expression, it's a multiplication expression, so we should put a bracket around that to identify that is an expression. We know that this thing, and we haven't really talked about what a function call is, but we know that it's an inseparable unit. There is this whole thing, like when we put the parentheses together with the identifier in front of it, that's called a call expression, so there's a set of brackets that need to go around the call expression because that's one coherent unit of stuff that happens. So, we've got our bracket around those. Let me do a little clean-up of my white space here so that's an expression. Now, we have kind of an interesting question to ask, which is would the programming language, would the computer think of these two things as an expression first, or would it think of these two things as an expression? Because we have two different operators; they're called binary operators. That's a fancy way of saying it's an operator that requires two different sides. So it's a binary operator plus that requires one thing on the left and one thing on the right and puts them together, and then the multiplication operator's the same way. So it can't do both of them at the same time. It's got to do one and then the other, and that leads us into a discussion of what we'd call operator precedence. Now this is not necessarily a critical set of rules that you have to learn, but awareness that there is such a thing is the important part, not actually knowing each individual nuanced thing. There's a set of rules that tells the programming language how to know what to do first. It doesn't always work in left to right fashion. Sometimes it could work from the right-hand side and then move its way backward. Now I accidentally, literally I just made it up, and I accidentally chose this multiplication to happen first, which happens to matter because multiplication is what is said to be more precedent. Multiplication happens before addition. If there's a question as to which one should happen first, pick multiplication before addition, and that's what we mean by precedence. So, we could say that this thing is an expression because it is the thing that the computer would do first before considering what's happening on the plus. So now, if you're not getting lost in this sea of brackets, you can see that I have one expression here, and I have one expression here. Those two are the binary operands, another fancy word, to say the values that go into the plus operator. So now we have one more wrapping of brackets. This is getting out of hand of course, but we now have a wrapping around that entire thing. Now this is one big complicated evaluation to take b * 2 and add it to the result of calling foo with c * 3 passed in. So we'll put all of that together to be an expression value, and that expression value, of course, then gets assigned to the left-hand side to the a variable that's over there. And finally, one last set of crazy brackets around the entire assignment expression, and now we've identified all those different little pieces that nest themselves together to become what we call a statement. Of course it looks a lot easier to read when we don't have all those brackets in, right? So, if I go back to the original statement without all of those crazy brackets in, we can come back to that same understanding. We can say hey, I know I need to do c * 3 because that's got to get passed in. So find out what c is currently, whatever value it is, and multiply it by three, and then pass that into the function foo. And again, we'll cover call expressions, what functions are, and we'll cover that in a little bit. And then whatever that value is, add that to the value of b * 2, so compute b * 2. Now I have two different things. Add those together, and whatever that final result is, assign it into a. By the way, the reason why operator precedence matters is that because mathematically this could mean two different things. If I was to simplify it and I was to say 2 * 3 + 4, mathematically it matters which one you do first. Two * 3 + 4 is 10. Two * 3 + 4 is 14. So mathematically it matters, and that's why this ambiguity has to be resolved by the programming language. The way we resolve that in programming languages is to understand a basic concept of operator precedence. Now, what if you were in the scenario where you wanted to sort of override that precedence? Yeah. You'd want to add parentheses. You'd want to add parentheses, exactly. You'd want to add them in your code just so that you could accentuate what you're trying to do. That's exactly the point that I was going to. Great segue. So, if I wanted to suggest that this program should do 2 + foo and then multiply that by b, then I could forcibly do that by putting in the parentheses. These here are not made up visual things. These are actually things that matter to the program. The parentheses here say do the stuff inside of the parenthesis first before working your way out. So now I have forcibly changed that rule, if you will, of precedence by forcibly saying that the plus should happen before the multiplication. Exactly the same as in the 2 * 3 + 4. I could've done that by saying no, no, no, what I really want you to do is come up with 7 first and then multiply it by 2. So those parentheses in this case, they matter. They matter to the end result. But what if I did want the b * 2, and I didn't want the 2 +? I want it to happen the same way as operator precedence. To the point that was just brought up, I can still put in a set of parentheses here. They're not necessary to the functioning of the program. They don't change the outcome of the program. It's still going to do exactly the same thing as if I left them out. But here's that point that we were talking about earlier where it's this balance, this goal to try to make sure that your code is understandable. If we put something into a program that the computer doesn't care about, then the only other reason for it could be that a developer cares about it. So a developer here not needing to know the rules of operator precedence doesn't have to understand whether times or plus happens first. If all they understand is the fact that parentheses wrap together, then they can process through this program and say clearly I should do this thing first, and this thing, and then add them together. So for readability sake, you would probably tend to want to put the parentheses in. Basically the take away here is that even if you know intricately all the rules of operator precedence, you don't always want to write a program that relies on them. Sometimes it's helpful, but sometimes it's more appropriate to add additional things to your program, like in this case an optional set of parentheses to make the code make more sense. Question. My question was without the parentheses, will it get the value of the function first or the variable b? That's a great question. So, if I didn't put this parenthesis here, what's going to actually happen? Well, the rules of operator precedence say if two different operators show up in a line like this without any other kind of grouping, it's going to say which thing happens first. So, from a left to right perspective, the b * 2 is going to happen first before calling the foo function. If the foo function had been in the left position, then the foo function would've been called, and then the b * 2 would've happened. So, the programming language does typically and generally move in a left to right fashion meaning that something on the left is typically going to happen before something on the right. Even if we looked only at this expression right here, the b * 2 expression, we could say that the programming language will evaluate the thing on the left first before evaluating the thing on the right. So typically it's going to work in left to right fashion. The only time when that is broken is if there's something like operator precedence, or there's another related concept called associativity, which we don't need to get into, but if precedence or associativity overrides that left to right behavior, and those cases it could force something to happen. So, if I were to simply reverse these two and say b + 2 * foo, now we know that operator precedence is going to say don't --- I mean we are going to evaluate the b part first and evaluate the 2 part first, but here we're going to call this foo function before we add it to b because we've got to compute that whole expression first. So operator precedence can work to sort of tweak the way this normal left to right processing happens, but overall you still see that even inside of each expression it still works in a left to right fashion, so that's a great question. Yeah, I like what's said in the chat room, be kind to your future, more elderly self. That's definitely true. Yeah. I'm probably getting way ahead of myself, but is there any difference between specifying as 2 or 2.0? Does it matter? In some languages it matters. In JavaScript it doesn't. In JavaScript, 2 and 2. and 2.0 are all the same value because there's just one number.
-
Executing a Program -
Okay, so let's go back to the text. I know I kind of jumped around a little bit and all. Well, let's get ourselves back on track and make sure we understand, or that we track back with the text. So, we'll come back to, and the next topic that's addressed is what we've only talked about so far is how to think about what a program is structured in and maybe start to think in our brains about what we do if we wanted to do it, but it turns out that it's much more important for the computer to run our program in the end than it is for us to run our program. So, it is that duality, as was brought up before, between needing to be able to look at a program and understand what it should do, and then being able to rely upon the computer to do what it actually must do. And those are two really important halves of the brain, if you will. So executing a program, what does that mean? Well, essentially it means turning the statements that we've written like a = b * 2 into low-level instructions that a computer can do something with. The computer itself would look at a = b * 2 and have no idea what that meant. JavaScript knows what it means. JavaScript needs to translate it into something else that then can be translated and translated further and further down the stack until eventually you get to that series of 1s and 0s, and the computer says ah, I know what to do with that. The 1 means put an electrical charge in, and the 0 means turn it off. And I can switch back and forth between 1s and 0s really fast and run all those things through the circuitry in my computer's CPU and out pops a number, right? So, it's this process of getting something from this high-level language, like JavaScript, this a = b * 2, which isn't exactly like natural language. It's not like I said it'd be interesting if there was a programming language where I could say set the variable a to the value 2, right? There are languages that are even higher level than JavaScript is, and so understanding that sort of, what we call it in programming, we call it abstraction. At this level, it looks like an English sentence. There would have to be a translation from that into something lower level because the computer would look at that and equally be confused, so a translation level would go from that to maybe something like a = 2, right? And then something would have to go from a = 2 down into another layer. And we might be getting too far afield, but I just want to make sure you understand. So the next layer down might be something that people refer to as assembly language, which is still a high-level language. It's not a 1 and a 0, but it's lower level. And I don't even remember my assembly language, but it's something like mov a, 2 or something like that, or 2,. I think it's 2, a or something like that. But that lower level thing is like I got these two different registers in memory or whatever and move one into the other, right? And then finally, at the lowest level of the stack, it's taken that thing down into a series of 1s and 0s that's really, really long, and that 1 and 0 string tells the computer what to do. So, what we want is we want to figure out to execute my program, of course we don't need this top level, but we definitely need this a = 2 level, we need something to convert it from that layer down into the next layer. There'll be something else that handles it on, on, on, and on, however many steps it needs to take, but we need something to do that first step, and that something is the JavaScript engine, the thing that's built into our browser, the thing that you can invoke in the developer console. If you were doing programming on a server, there's an environment where JavaScript can run on a server, and, I mean, there's all kinds of different places. JavaScript can run on watches and inside of light bulbs and whatever, but in every place that there is, there's a JavaScript engine that takes something like a = 2 and turns it into something that that environment knows what to do with. And that's what we mean by executing a program is taking that source code that we've written in text form, converting it into something that the next layer down knows what to do with, okay? Now, quick little kind of myth busting thing. It is often said of languages like JavaScript that they are scripting languages. Of course, the word script shows up in JavaScript, so it's natural to assume that it's a scripting language. And it's also often said that scripting languages are interpreted. In other words, one statement at a time. It works on that statement, and then it goes to the next statement, and then the next statement. So when it's working on the statement on line three, it has no idea what to expect of line four because it hasn't gotten there yet. It's like if you're working through a to-do list, and you're like I don't even care about item two yet because the top item on my to-do list is the only thing I'm thinking about, right? Well, that's what we mean by interpreting, and there are languages that are, in fact, interpreted like that, that are interpreted line by line by line. An example of that might be something like a command line scripting, like Bash or whatever. It's not fully interpreted, there's a little bit of nuance there, but it's essentially interpreted line by line, and it's oftentimes assumed that JavaScript is the same way. It's oftentimes assumed that JavaScript is interpreted with line one and then line two and line three. There've been many books that have said that. And it is true that in the very earliest days of JavaScript it worked a lot more like that. It's definitely true that when Brendan was first inventing it as a prototype he didn't really have all the time to go through all the sophisticated stuff, so he had to make --- just bang something out quickly and cut a lot of corners, and so it essentially in the very beginning it was kind of that way. But very quickly JavaScript matured, and by very quickly I mean within those first couple of years. JavaScript matured to the point where interpreting it wasn't really practical anymore, and yet that myth propagates even today. And people say JavaScript's a scripting language, it's interpreted, it's not ---. And the other option if it's not an interpreted language, the other thing that we talk about is what's called a compiled language. And what a compiled language and an interpreted language, the way that they primarily differ is not the way you might think that they differ. Most people think about the difference between an interpreted language and a compiled language as that a compiled language gives you this physical binary file thing, like on Windows it's a .EXE file, or on a Mac it's, I don't even know what it is on the Mac, but there's some like executable file on the Mac that you can run, or when I compile something in Visual Studio and I put my program on a, nobody does this, put it on CD or DVD anymore, but that's the way you used to distribute in the old days of programming. You'd put your program on a CD and sell it to people. So, most people think of compilation as I'm producing some physical series of 1s and 0s and putting those into a file that I can send that series of 1s and 0s to other people, and they don't need to process it, they just need to run it. And they think about interpreted languages as not doing that, that every time you want to run it, it has to reprocess from the beginning. So that's one way of thinking about the difference between interpreted and compiled, but the more important distinction, the one that matters to JavaScript is that compilation means that there's more than one pass through your program. What do I mean by a pass? Let me try to illustrate that because I could be getting off field very quickly. So, if I have a = 2, and then I have something down here like that, well 2 open close parenthesis kind of looks like a function call, but it's not valid because you can't have a number in the place of an identifier. So, as JavaScript language is concerned, line two is an error. It's invalid. It's actually syntactically invalid. It's not a runtime problem; it's an actual authortime problem. I was an idiot, and I put the number 2 in a position where I meant to put a letter. So, in an interpreted language, if I was purely running line by line by line, and I wasn't doing multiple passes, I'd run line one first, and then I would discover that line two had a problem, and I'd throw an error. But in a compiled language, the first pass is not concerned with executing the program. It's concerned with understanding the program. It makes a pass through this program, and it figures out if the program is valid. Does it match all of the rules? It would be like scanning through a novel and looking at all the things to make sure all the sentences had their periods on them, and then going back and reading the book to understand its content. That's the difference here. So a compiled language would say line two's a problem, and it would flag you with that error before it ever tried to run line one. Does everybody understand the difference there? Make sure that people aren't --- hopefully people aren't missing that distinction. So JavaScript, in that respect, is more a compiled language than an interpreted language because JavaScript definitely does look at line two first before it's ever tried to run line one. It looked at line one to understand what line one was about, but it didn't run it. It just looked at it to understand it. And then it looked at line two to understand it, and when it saw that line two was invalid, it said I'm not even going to try to run the program because it's not a valid program. So when you put a program like this, if that was in a file and you loaded that up into a browser, line one would never run. You'd immediately get an error saying line two is invalid. Whereas if you put this into a scripting language, like a Bash or something, line one would run, and then you'd get an error on line two. And that's the major distinction that we want to make between this compilation versus interpreting. The good news is that because JavaScript's compiled, a lot of these mistakes that you can make in your programming are going to get caught at the very beginning before you've had a chance to mess something up. You try to run your program, and the first thing that happens is it gets compiled. And if the compilation throws an error and says hey, you've messed up, that's not good, then you know what you need to fix. It'll tell you line 2 is invalid, 2's not a function, or whatever. Okay, so that's the distinction we'll make, and we'll kind of leave it there. There's definitely more details, and I expound upon that a lot more in the Scope & Closures book in this series. But we'll kind of leave it for there, think of JavaScript more like a compiled language than an interpreted language. And it doesn't really matter that JavaScript doesn't get put into binary form and distributed the way EXE files are. What matters is that JavaScript gets compiled for error checking.
-
Practice Coding -
The next observation that we want to make, which follows along with this understanding of execution and the fact that a program needs to get run is that there is no substitution for running these programs yourself. So while you will see me for the visual purposes, I'll do a lot of code writing in my code editor. And in a code editor it's not actually running anything for me. An IDE might, but there's no running environment here, so it isn't checking my program. You're going to want to run these sorts of programs in an actual JavaScript environment, and it turns out that one of the easiest, lowest hanging fruit ways of doing that is if you're in a browser you can open up the console. So I'm using the Chrome browser. There's a question. The question in the chat room is JavaScript provides you an error on runtime, right? JavaScript has both. It has both what we call static errors, that is something where the compiler said hey, that's invalid syntax; you did something wrong. It also has runtime errors where the syntax was correct, but that you tried to do something invalid with that, like you tried to assign to something that was read only, or you tried to run something as a function, and it wasn't a function. Those are runtime errors. So JavaScript has both. What's an interpreted language in a nutshell? Yeah, essentially, it's going to take it line by line. When it's on line three, it doesn't know what to expect of line four. A compiled language looks at and understands all four lines first before trying to run the first line, so it implies that there are multiple passes happening. So if I'm in the Chrome browser as you see here, most people know about keyboard shortcuts if you get into development, so Command+Option+I on a Mac in a Chrome will pop up your developer tools, and I have mine set that it defaults to popping up the console. If you're looking for a way to do it manually, you can come over here, and in your Chrome Developer Tools there's a More tools, and then you can go directly to the JavaScript Console, and it's going to do the same thing. Yours might pop up on the right-hand side; it might pop up in a separate window. I like to keep mine anchored to the bottom of my browser window. But it doesn't really matter how it shows up to you. Open up your JavaScript Console, and you'll notice that it's kind of like we can just type some code in, and it's kind of inviting to us, like type some code. So we can literally just type some code. I could say something like a = 2. And if I hit Enter, it's actually going to run that statement as if that statement was a program. Now I'm going to refresh my environment, and I'm going to go back to this program here, the a = 2 and then the 2(), and I'm going to run this. And what you're going to see when I try to run that program is that I get an error. This error says 2 is not a function. In other words, it checked the program first. There's no a that has been run. It was invalid to try to run 2 as a function. There are lots of other syntax errors that we could come up with. So, for example, if I had 2 = 3, the value 2 on the left-hand side is not something that can get assigned. It's not a variable, so it can't get assigned something. So that is, yet again, an example of something that can be caught kind of at the compiler phase. You've written something totally invalid. But here's something that can't be caught at the compiler phase; it has to be runtime. If I say something like a(), open close parenthesis, what it cannot know is if at that exact moment of my program is a a function or not? It doesn't know that yet. So it has to run the program, and if it fails, in this case it's failing because there isn't an a, that's a mistake, so let's make there be an a, and then let's try that a open close parenthesis, and you'll notice that it fails as a type error because a doesn't have a function value in it. If a had a function value in it, then the function call would've worked. So that's what we meant between the distinction between compiling something, knowing ahead of time that it's broken, versus needing to try to run the program to find out if it works or not. (Reading) Hopefully the most recent question in the chat room has been answered. JavaScript catches invalid syntax by compiling your program first and then executing the compiled code as opposed to a scripting language which can't catch the syntax errors until it gets to them. Okay, so it's important to try from here on out to run programs in an environment, and the easiest way for you to try that is something like your developer console. There are other ways to do this. There are sites like JSBin and JSFiddle and a dozen other ones out there that you can go to the site and type in some code and run a program. Those ones are fine too. For our purposes, I think the most basic is the best. Just try it in your console. So essentially what I'm asserting here in the book is I'm saying don't just take these things for granted that if I say a = 2 it works. Try them yourself. One other little kind of a tip here is you'll notice that I can do a = 2, and if I hit Enter all by itself, it'll run the program, but if I hit Shift+Enter, it gives me a second line so I can keep going. I can enter in a multiline program by hitting Shift+Enter. And most of the developer consoles are kind of like that. You can do multiline input. In my case, I'm going to prefer to write my code in an editor and copy and paste it in just so I don't have to keep hitting Shift+Enter over and over. So you can go either way, but knowing about the Shift+Enter technique is good. Okay, so in that case, the question in the chat room is if I try var a; a(). The reason you're getting that it's a number is because your environment still has a assigned a value 2 from when you typed it in earlier. So you've been noticing that I've been refreshing, and I do that with my keyboard shortcut. I do Command+R in the browser in Chrome to refresh an environment, to start it over. So, you can do that, or you can hit the refresh button or whatever, but making sure that you start with a fresh environment is a good way to avoid accidentally having it as value 2. Question about running JavaScript from like the command line. Yeah, there was a question about can JavaScript be run from a command line? There are command line execution environments, the most notable of which is Node. Node is typically cited as kind of a server-side JavaScript environment, but Node can also run command line programs. So you could, if you had Node installed, you could run Node - e, and give it a JavaScript program, and run it from the command line, or Node and give it a file name kind of like you're talking about with Java. There are other JavaScript environments outside of browsers. So Rhino is one of them. There are probably maybe three or four others that I'm forgetting off the top of my head. There are some JavaScript command line environments. The most common is definitely Node if you want to run JavaScript on the command line. Yeah, Node, io.js, they are forked versions of the same project. Looks like they're probably going to come back together in a few weeks or months, so I'm using Node to refer to that whole family of server-side JavaScript. And yes Node does have a REPL, which looks a little bit like our thing here. It's like an actual environment. I can illustrate that real quick because I have Node installed on my computer. So I can say node, and now I'm in a command line environment where I can do var a = 2 and try to run the program, and I'm going to get my errors. Alright, so Node does have a REPL like that. But also, if I had a file with that code in it, a =, I can't even type in Vim anymore. Okay, so if I had a file called test.js and I said node test.js, it's very similar to Java's command line environment. So you can do those things, or you can do node, I think it's -e, and then give it a string of code like a = 2. I think that works. Yeah, so -e will evaluate it from the command line. So there are command line environments. I would suggest it's probably better to stick with your developer console while you're learning JavaScript, but there are command line environments if you want to play with them.
-
Input and Output -
Okay, We've got input and output as the next topics. The most traditional of all outputs in JavaScript is to do an alert statement, and that alert statement, which you can try yourself, you do alert("Hello World") like that. That alert statement pops up a pop-up box in a JavaScript browser, but it's important to understand that the alert function itself is not actually part of JavaScript. It comes from the browser. So alert itself, it's not defined by the JavaScript language or anything. It's given to you by the browser. And if you tried to run alert inside of say Node, it may very well not have that because there's no such thing as a pop-up box inside of Node. So, the much more common way of doing output that we can work with as developers is actually the console.log statement, and console.log logs a message to your console, which happens very conveniently to be the thing we're already working in. So when I say console.log, I'm actually going to print that message right back into the console I'm already working in, which is super convenient for us. So from an output perspective, you can be much more sophisticated, like putting stuff on a page, putting an input box on a page and assigning a value to it, and then its output in terms of visual. But as a developer playing around in the console, console.log is kind of the simplest way to print out some messages. So if I had a var a = 2, and then I wanted to print out the current value of a, I just say console.log, and I just give it the variable a, no quotes, and it prints out the value 2. Another little thing that is kind of annoying about these consoles is that you notice a lot of times you end up getting this undefined being printed in weird places. The console environment in your browser is designed to take the very last statement expression in a program and evaluate it for a value, and then show you that value. So, for example, I'll get to the question in a minute. For example, if I say a = 2, remember that was an assignment expression, the result of an assignment expression is the value that was assigned. So the JavaScript engine just does an assignment, but the console does one extra step, which is to say whatever my last statement is, give me that value back. So that's why it prints a 2 here. And in statements that have no return value, you get something like undefined. Like, for example, a var statement has no return value, and that's why we get undefined. There was a question. They're just wondering why is undefined returned? Hopefully I just answered that. Because there are statement expressions that have no return value. Okay, so that's our output that we'll use, is console.log. Now, we're not going to use input a lot, but just as a side note if you did want to receive input, a lot of times, most of the time you're writing that by having interactive elements on a form, on a page where people can type in their name or whatever. But again, if you're working purely in a sort of command line-ish like environment like this console, another way of receiving input is the prompt statement. So we could say something like var age = prompt, which is a function, and we can give it a message to ask, so I could say, What is your age? That message that I ask is going to pop up in a pop-up when I hit Enter, so we see here, What is your age? And it's given me an input box and asks me to type in something. I just turned 35 a few weeks ago, so I will hit 35 and hit OK. Now that value goes back, and it has been assigned to this variable age. So if I then say console.log(age), I'll get 35. So try that yourself. Try writing a prompt, asking a question, giving it a value, and then testing the return result was assigned. So the question is is that value a string or a number, or what is it at this point? What if you wanted to make it a number? We'll probably get to that, right? We do get to some value coercions in a little bit. The thing that comes back from prompt is always a string, but it's easy to make it into something else. Yeah? Do you not need a semicolon after the first statement? So that's an example of one where I should've put one for clarity. I was lazy and silly and forgot it. So JavaScript is forgiving in a lot of places. That's what I meant earlier when I said that semicolons can be optional in a lot of places. It's forgiving, and it tries to put them in if you've forgotten them. I should, in proper coding, have put a semicolon there. (Reading) Okay, hopefully, even if this is your first experience with JavaScript, hopefully you're starting to get a slightly more sense of what we're going to do. We're essentially going to make some variables. They're symbolic containers that we can put values into. And we're just going to figure out different values and assign them back and forth, and maybe along the way we might output some stuff with a console.log. And that essentially is the basics of writing a JavaScript program. You can get lots more complex and write JavaScript to manipulate the page and make network requests, AJAX, and all of that stuff, but none of that is necessary to learn the language JavaScript itself. What's necessary here is to understand basic things like how to make a variable, how to put a value into it, and so forth. So hopefully, input and output will be ways to explain some of this stuff.
-
JavaScript Syntax
Operators
The next topic is operators and we have dealt with operators already in several places. We've had the plus and the multiply and we've had the equals; we've already seen several operators. It turns out there's probably 30 or 40, 30ish or something like that, different operators defined in JavaScript and I've got a listing here in the book. I'm not going to bore you by giving you every single one of them, but there are a whole bunch of different operators that all do different things and if you want to read up on it, you can read this. These are kind of like the most important ones and then there's even more listed here on this MDN link. So being aware of what operators are available to JavaScript is of course really important because you're going to want to do stuff and the stuff you're going to want to do is going to need tasks. There are going to be places where there are multiple ways to do the same thing. So for example, this statement right here; I'll copy that and put it in my code editor so it's easy to read. This statement right here, a = a + 2, we can already kind of intuit that what it's going to do first is get the value out of a, whatever it is, add 2 to it, and then assign it back to the variable a, okay? So in other words we're just adding 2 into the current value. So that's one way of doing it and that's a pretty clear way of doing it, but there are shortcut operators which some people like and some people feel are more complicated, but in this case there's a shortcut operator. If you want to take a variable and add something to whatever is in the current variable, then a shortcut operator is putting the + and the = together and then just whatever you want to add on, and these will have the exact same end result. They'll take whatever is in a currently, add 2 to it, and put it back into a. So it turns out there are several different says to come at any given problem. Knowing the different tools that you have, you can choose. Now again, I kind of referred to, some people prefer line 1 and some people prefer line 3. They both do the same thing. The question you should ask is, which one semantically means more what it's doing and I would tend to say that even though line 1 is more explicit, it actually might take a little bit more brain power to understand line 1 than line 3. If you learn the line 3 operator, you know that it just adds something to my existing variable and I don't have to think about the step of pulling out the value now; it's current in adding it. I just say, put another 2 into the bucket. I've got a bucket of eggs, put two more in, right? So line 3, to me, is slightly more conceptually simple once you learn that that's a shortcut operator and looking at it in code, if my only goal was to 2 to whatever it is, I might prefer this line 3 over line 1. That of course might be quite controversial because there might be people that vehemently believe that line 1 is way, way better and more sensible. So the point of illustrating is that readability or understandability is inherently and completely subjective. That statement of make a readable program, or make my code more readable, those sorts of things are thrown around an awful lot. Most of the time people don't have a precise meaning for what they mean for that. There is no precise definition of what readable means. It's subjective. It's subjective to you and it's also subjective to the other people that you expect or intend to read your program. Is there a question here? They're just asking if minus; when subtracting f - = does the same thing but for subtraction, so - = would take a subtract it out just like a = a-. So there are lots of operators to learn in JavaScript. The major ones that we care about are the = operator because we're going to do a lot of assignments and maybe the math operators because that's just a simple way of illustrating concepts, so the + and -, the * for multiplication, the / for division; those ones are pretty important and then all these other ones like another one that you'll probably want to learn is the == and the ===. For our purposes at the immediate moment, they do the same thing which is to check if something is equal. They are not the same, but for our purposes, they compare, they check equality. So over the break there was some discussion, some good discussion and questions in the chat room and I will just say, we're going to deal with the differences between using var to declare a variable and not using it. We're going to cover those differences in a little bit; that comes a little bit later in the chapter, so we'll come back to it. For now, the only difference that we saw was just the difference we could observe, that var a = 3 results in undefined, even though a has 3 in it, the var part is undefined, or the var part returns undefined, but later if we say a = 4, or even just a = 3, but a = 4, we're taking a value and making an assignment statement out of it and that statement does have a return value which the console finds and hopefully prints out for us as the value 4. So that's just an observational difference about the behavior of the console; it doesn't mean anything at all about the appropriateness of using one or the other in your program and we'll come back to that later.
-
Values and Types
We've been throwing around some concepts and we want to come back and layer those in if there have been some things that maybe were missed. If I have the value 42 and another way of expressing a value that looks very similar to put some quotes around it, these two values look like they are, you know, roughly the same. If we were to print out both of them, they would both print out in the same way. They'd both say 42 and have the literal characters 4 and 2 after each other, but they are going to behave differently in our JavaScript program and that is because these values are intrinsically of different types and that word type, we don't mean physically putting, you know, your fingers on keys on a keyboard. We mean it is an intrinsic behavior of the value as expressed. So this 42 that we see on line 1 is a number and the "42" is what we call a string and numbers have different behavior associated with them than strings do. So for example, numbers are what we do math with. We can say 42 / 2 and that gives us 21. Strings are what we do input and output with. Strings are also how we deal with characters so if I wanted to say, what is the first character of the string 42, that bracket 0 could tell me that the first character of it is the character 4. So the character 4 is the first character in the string 42, just like if I had a string abc, the character at the 1 position is the character b, okay? So strings are accessing things character by character, numbers are what we do math with and these different intrinsic behaviors are important to keep in mind because if I express the number 42 in my JavaScript program I am signaling that I intend to use that in a mathematic way and if I instead express "42" in my program, I am expressing that I intend to use that in a string way. Yes? Is the use of single versus double quotes important? In JavaScript strings can either be double quotes or single quotes; you can't mix, like you can't have double quote in the beginning and single quote in the end, it has to match, but they can either be all, you know, double quotes or single quotes in terms of your delimiting of a string literal. There is no difference whatsoever functionally in JavaScript. In fact, stylistically, the only arguments that can ever be made are some people prefer the single quote because it's less keystrokes for them, they don't have to hit Shift. Other people prefer the double quote because it's more natural that they've done that in other languages and is purely a stylistic thing. Here is what I would say. Never, ever mix. Do not have part of your program using single quotes and part of your program using double quotes. Pick one and I really don't care which; you can pick whichever one you want, there is no difference, but pick one and stick with that consistently throughout your program. You will see that prefer double quotes. I use double quotes. Okay, so these numbers, I mean these values have these different types. So if I said var a = 42, I've got 42 that's in an a variable. Let me take off the var part just to not confuse that now, so I'm just making an assignment. The a variable is going to have the 42 in it and if I wanted to print it out, I can say console.log(a) and you'll notice that the JavaScript engine dually does print that out. If we try this program, you'll notice I see 42, but happens if I said a = "42" and then I said console.log(a). It's very subtle and difficult even on the projector to tell, but this one is printed in blue characters and this one is printed in black characters because the console is giving you a very subtle hint that underlying what it's done, it was dealing with a different value type. So it's important to understand and this is actually, it's not really incorrect in the book, but there is a slightly misleading thing that I'm going to correct in a second edition. When it talks about console.log, it suggests that console.log changes everything to a string. Actually it doesn't really change it to a string when you're running inside of your JavaScript engine. It just prints out whatever thing you had, so that's why we see a slightly different representation there. There are other contexts, which is what I meant. There are other contexts that change things into strings. So for example, saying alert 42 or a variable with the number in it, changes it into a string so that it can print it in the box. So we can't tell any difference inside of an alert box, whether it had a number or a string, but we know under the covers it needed a string to do it, so it actually converted it to a string. So if I wanted the string representation of this value, if I had it as a number and maybe then I later did like some division. I said a = a / 2, so now we know a is holding the value 21, and if I then wanted to do something string oriented with it like output or getting at its character or whatever, I would need to convert it into a string. Convert from one type to another, and this conversion is common in all programming languages. All programming languages have a notion of conversion. In JavaScript the word that we use is slightly different; it's not conversion, it is coercion and some people like to nitpick and say well, there's one thing that's conversion in JavaScript and another thing is coercion. I find it much easier to actually distinguish between explicit and implicit rather than conversion and coercion, that's one is more confusing to me. So an explicit conversion, one that it's obvious that's what I'm trying to do, if I wanted to turn a into its string representation, I could literally use the string function and that's going to convert and that might look, if you have any experience in another programming language where they do type casting or other forms of conversion, that looks very similar. So I'm explicitly saying, take the thing that's in a now and if it's not a string, make it look like a string and then assign that value back into a. So if we took this program, if we put a console.log on it, if we took that program and we ran it, are we expecting a blue number for the 21, which would be that it's a number or are we expecting a black character for 21 because it's a string? We'd be expecting black because it's a string and in fact we get black. Again, it's really subtle on the projector in the stream but this is black 21 because it's actually a string representation that I printed out, exactly the same as if I had said console.log Hello World. Okay? Alright, so strings serve a purpose in programs differently than numbers do and converting between the two is almost always required. We saw that we could say a = string(a) to convert from anything into a string. If we wanted to go the other direction, like go from a string to a number, like if we had another variable called b and we said b, then we could do the same thing, but with the number function. We could say number a. So now b is going to be the number 21 and a is going to be the string "21." There's a question in the chat room about changing things. This is a subtle point which I don't want to belabor too much, but, which we will actually get much more into when we talk in the morning session of day 2, when we talk about coercions and all that stuff in much, much more detail, but just as a brief answer, in JavaScript variables do not have types. There's no such thing as a variable having a type. In JavaScript the value has the type, so the value 42 or the value "42" is the thing with the type and the variable, the thing that we call a or b, it has no type. It can have any value of any type in it, whereas in other languages that are called static languages, those languages you don't declare a type on the value so much as you declare a type on the variable itself. So in c, for example, if I say int a, I'm saying this variable container must hold only ints, integers. So I'm typing the variable itself rather than worrying about the type of the value. So that's just a distinction. In JavaScript and in other dynamic value languages like JavaScript, we don't have a value for the variable, we don't have a type for the variable, but we have a type for the value. The return of a variable color code matters. The only point that we are making here is to understand if you're going to program inside of the console, understanding what the console is doing. It has special behaviors that are outside of what JavaScript itself is doing. So here I'm just helping you understand the console. If you see blue characters, then the console is telling you that you had a number and if you see black characters, the console is telling you that you had a string. That's just a subtle nuance of working with the console. It does not matter actually to the JavaScript engine. Okay, so we're not going to do much more about coercions except for me to suggest that those two that I showed you before, these are explicit and there are ways to do implicit coercions. So a way to go from a number to a string that is sort of a side effect of some other operation; that's what I mean by implicit. It's not obvious that you're doing it. So if I said something like right now we know a is the number 21, if I said a is = to a + and empty string, again without getting too much into the weeds about how the plus operator works. In this case the plus operator wants to do string concatenation instead of mathematic addition and because one of these things is not already a string, it has to make it into a string. So under the covers it's going to do that string a thing that I was showing you, but it's not obvious to us that that's happening, and yet if we try this program, and do a console.log on that a variable, if we try this program, we'll notice that we're going to get those black characters because it's going to have made it into a string value. Try that in your own console to verify whether or not you have that third line in or not and you'll notice the difference between getting black characters in your console or getting blue characters. Is there a question back there? Would there ever be a time where you would want something to not change so it would be final and so even in an instance like that, it would give you an error, let's say, instead of converting it behind the scenes? Like you don't want that to change in your program? There's a question in the live room here about whether or not there's a notion of wanting a variable to have sort of a final value in it. That is if you tried to do something else and assign it a different value, it would throw you an error and there is actually that notion as of ES6, the newest, latest and greatest JavaScript that's coming out. There's a notion instead of using that var keyword that I've talked about a couple of times, you can use const to create what's called a constant and other programming languages also have a notion of a constant. So that's getting a little out of our topic, but just to make sure we're clear on it, if I said var a = 42, I'm making an a that can be changed as many times as I want, but if I said const a = 42, I'm making an a that can never be changed again and if I do a = 10, it will either silently fail or actually throw me an error and that depends on strict mode, which we may cover later. But const is the way you make a variable that can't be changed later and that's only in the newest versions of JavaScript.
-
Code Comments
I've a section in here that mentions code comments. This is one that people actually thank me for putting in because a lot of people don't actually do this very often or they don't have this habit very often, but I think it's a habit that you get into. If I declare something like var a = 42 in my program and that's just a number that comes out of nowhere, if I come back later and I'm like, where does that number come from, if I don't remember why I assigned it the value 42 then my program is less understandable. So a way of making a program more understandable is to write better code, but another way of making a program more understandable is to put code comments in and what code comments are, are things that are ignored by the JavaScript compiler, the JavaScript engine, and they're only there for a developer to read. It's like a cheat sheet if you took it into an algebra test or whatever; it's just there for you, it's not there for the computer. So if I said something like 42 is the meaning of life as a code comment, then later when I come back then I've explained what the heck I was doing here, alright? Code comments are an incredibly important thing to put into your code. They come in two forms. There's the form here where it's a single line comment. There's another form where I can literally put multiple lines into the same comment. So if I had two different statements like b = 12, and I needed to say something longer about it, I could do a multi-line comment which starts with /* and I have to have another */ to end it, and I can have as many lines here as I want. Line 1, line 2, line 3, and the syntax highlighting in my editor suggests to you where those boundaries between comments are. So the // is always a single line. It takes over everything from then on. So I can either have it on its own line or I can put it on the end of an existing line. A multi-line comment can appear anywhere so I can literally put a multi-line comment right inside of the middle of another statement if I really wanted to because it can appear anywhere. So you might do it like that. Like this would be silly, but you could say something like 42 is the meaning of life and you can do it multi-line like that, okay? I won't belabor that point anymore but you want to practice writing code that always has good comments in it and let me give you a quick little pointer. How do I know what comments should I put into my program? This might be the most important thing to take away from this part of our discussion. Comments should never say what. Almost never should they say what. Your program says what. A = 42. I don't need a comment that says assign 42 to a because the code does that. A comment doesn't say what, a comment says why, or alternatively, if you've had to write a line of code that could be confusing, you could explain how. So a comment should be the why and/or the how, not the what and that's what makes for a good program, for good comments. So in a program that has 100 lines of code that looks like these two do here, if you had 100 lines of comments like one line of comment for every line of code, you might be doing it overkill, right? Or if you have more comments than code, that's almost certainly overkill for a program, unless of course you really do have a lot of why and how to explain for a really short program. If you do that have, it's totally fine to have lots and lots of comments. You want to be as verbose as is necessary, no more, no less; that's the good rule of thumb. So focus on answering the questions of why and perhaps how and don't focus on repeating the what. I see a lot of times people write programs and the comments say what over and over and over again and I'm like, oh. I even do that. I have that, you know, mistake. I will explain a little bit about the how of a line or the why of a line and essentially I'm just repeating what the line of code did itself. It's unnecessary. I'm not going to go into a debate in the class. In the online chat room it asked if I could explain why Doug Crockford's The Good Parts say multi-lines are bad. I'm not going to get into a debate on what I do and don't agree with Doug Crockford on here. I've got lots of other places where I would say it. I'll just say flatly, multi-line comments are part of the language and I use them and his reasons for why are his own. He'll write his own books to describe his reasons why he says that. I could literally go on for days about debating what he says, but let's keep to the focus of what we want to talk about.
-
Variables and Blocks
Alright, now back to variables. We've mentioned this many times but we didn't explicitly define that and here is where it matters if you put a var in front of something. So if I have a program where the very first line says a = 42, I'm assigning to a variable that has never been formally declared and assigning to a variable that's never been formally declared is a really, really bad idea. Every variable that you use in your program should be formally declared and it should be formally declared before the first time you use it, okay? Technically this program formally declares a and uses it, but it makes use of this concept which we won't really get into. It makes use of this concept called hoisting and it's a more confusing program even though it's a correctly running program. Hoisting says that it declares it after the scope's over. Yes, I cover hoisting a lot more in the book on Scope and Closures so if you want to get into the nuances of it, it has to do with the fact that this program is going to get compiled first so it's going to find that var a before it tries to run anything, but this is a more confusing version of the program. You would always want to prefer for lesson confusing programs to write var a first before you do an assignment and you can optionally combine those two into the same thing, but you would always want to formally declare every variable and the way we typically do that in JavaScript up to this point is with the var keyword. There are two more coming in ES6. One is called let and the other one we mentioned earlier is const. Let and const are block scoping declarations rather than function scoping declaration like var is. What that means has a whole chapter in the book so I won't get into that too much, but those are the three ways that you formally declare a variable in JavaScript. There is one other way to formally declare an identifier and that is to declare it as a function and we haven't talked about functions yet, but if I said function a, I'm declaring a variable called a which has this function value in it. So you always want to formally declare your variables, in one of the ways that I just showed. Let me put those other ones back. Those are the ways to formally declare variables and you're always going to want to do one of those in your programs. What's the use of hoisting? Again, I have a whole section in the Scope and Closures book about what hoisting is about and hoisting is actually not a real thing, it's a metaphor for the real thing and the real thing is the compiler. Can you also discuss advanced JavaScript? We'll hope so here. I do extensively cover this topic in the Advanced JavaScript course that's available from Frontend Masters. Okay. There's a question about using let. What's the difference between using let to declare a variable? I don't want to get too much into the weeds so let puts it inside of a block; var puts it inside of a function. That's all I'll say about that. There is much more about that in the Scope and Closures book and in the Advanced JavaScript course. For your basic learning purposes in JavaScript, you don't need to worry about let and const. Var is more than enough, but there are nuances to their behaviors that are available to you, if you work in ECMA script, in ES6. Okay, moving along. There's a notion in many programming languages and JavaScript is no different that if I had a collection of statements like var a = 42, and foo a / 2. These are statements and if I had a collection of statements that represented a logical unit together, then I could put those statements together inside of a curly brace pair like we see there and that's called a block. A block essentially is a pairing of curly braces with one or more statements inside of it. Now this block is a completely stand-alone empty block. It doesn't mean anything the way we've expressed it. It's a stylistic thing. It says these two things belong together and they're separate from other stuff. Like if you had a program that looked like this and you had stuff up here and you had stuff down here, you're stylistically signally these two things in between, they're kind of special, they're set off, they're their own deal. So there's not any functional difference here. But most of the time blocks are not appearing by themselves like that. Most of the time they appear associated with another kind of a statement. So there are different kinds of statements that have blocks associated with them. For example, which we'll get into in a little bit, the if statement. So if I wrote a statement where I wanted to say if a was greater than 10 and attach a block to it, then what I'm saying is, look at this statement and figure out if that's true or false. Is the value currently in a greater than 10 or not? It's only one of two possible answers here. In our program we would have had to declare the var a and give it some useful value like the value 42, and then give it some other value down here. So if I said, if a is greater than 10, is the answer yes or no? Yes, it's greater than 10. Yes, it's greater than 10. So we go into the block only if we answered yes to this question. This asks a question. We go into that block and do these things only if the question answered yes. In programming terms, yes and no are actually what are called the values true and false. So the question is, is that statement true? And the answer is yes, it is true. So we would execute the stuff inside of the block, otherwise we don't. So that's one way to attach a block to something is to an if statement. Another way to attach a block to a statement is to have a loop, like a while loop or a for loop or whatever and we'll come to loops in just a moment, but you notice that this block again, it belongs to that statement and it's only going to get executed in the context of that statement. So it will only get executed if this loop is going to happen. In this case the loop is going to happen once because the first time we enter a greater than 42, but immediately we set it to 10 so the next time we try to do this loop, it's not going to keep going because a will no longer be greater than 10, it'll just be the 10 itself. So Kyle, do you have the bracket at the end where some people bring it down and have it at the beginning? Some people like it there, yes. What kind of person likes that? _____ Oh, I'm tempted to answer that, but I can't. Well, answer, go ahead. No. It's a perfectly valid style of programming. I've only seen Enterprise Java developers do that. I don't know that I would associate it with any particular group or people or even in a particular language. It is a stylistic choice only. Is it a bad choice to do it the other way? It's not a bad choice. It's a choice; not a bad or a good one. The vast majority of open source developer do what's called cuddling, which is that they put the curly brace on the same line as the statement. It's called cuddling? That's how most people do it, but there's nothing wrong with doing it that way. They are functionally exactly the same. Okay. So we have a block that's not associated with anything and means it's going to run every time, or we can attach a block to something and it means it's only going to run conditionally if that statement actually results in something that we want to do. There are lots of places where blocks can appear. Blocks can also appear as part of a function statement. So here, that block of statements only happens for this foo function. I probably don't want to call recursively so I'll call a different function here. Now this block only happens if foo ever gets called. So it doesn't run right away, but if later in a program I try to invoke the function, then it would find that block and it would run that block of code, okay? So just think conceptually, if I wrap a curly brace pair around a set of code, I'm putting that as a collection of code and then I can attach that block to various different kinds of statements and that will change how and if and when that block gets executed. That's the major takeaway. There is a question there to the bottom if you want to read it. The question was essentially you can declare a function like that, or you can declare a function like that and technically there's a third variation which is to give it a name itself, which doesn't have to be the same. Those are all functions. Those are not all function declarations. The first line is a function declaration. The next two are function expressions attached to a variable declaration. There is a variety of differences between these and we get too far off track if we worry too much about those nuance differences, so there's a variety of differences between them, but the major takeaway here that you would want to not forget is that in all three of these cases, the block is associated to a function and the block will not run unless you execute the function. So the nuance differences between function declarations and variable declarations with function expression assignments, those nuance differences are outside of our scope of discussion here. They are covered in depth in the book series, so next steps you want to pay more attention to that reading through the books, it's also covered in my training.
-
Conditional Statements
We mentioned that there was a kind of block called a conditional, an if statement. Let's focus more specifically on a conditional. If I have the variable a = 10 and I want to do something only if a is greater than 5, then I put an if statement around the block and here I say, a = a * 2. So I'm only doubling the a variable, I'm only doubling its value if it was already greater than 5, for whatever reason. The if statement says, take this thing, whatever this expression is, and figure out if it's true or false, but there are statement expressions that you can put there, which are not already true or false. This one is. The greater than operator always says that's either a true or a false. So the result of that operator is always either true or false, but there are certain expressions that we could put here that would not result in true or false by themselves. For example, that expression, which is extremely common in JavaScript. People put an expression like if a. The if statement still expects a true or a false and if you don't pass a true or a false, guess what has to happen? It has to convert. Remember we talked about type conversion before? I showed you type conversion with numbers and strings? Well, there's also type conversion between any value and what's called a Boolean value, that is the true or the false value. So this variable gets converted either to a true value or a false value and the rules for how that conversion happens are fairly straightforward. There's a list of values defined in the JavaScript spec which are called falsy values. Falsy, f-a-l-s-y, okay? So falsy values are defined as these: 0, -0, NaN which is the not a number number, empty string, false itself, null, and undefined. That list of values is the list of falsy values in JavaScript. And the easiest thing for me to say is, the way you figure out if something is truthy, that is that it's become true or it's falsy, it's going to become false, is to just consult this list. Memorize the list and then just mentally consult it. It is either a falsy value because it's on this list, or the only other option is that it must be truthy. It must behave as a true value when coerced. So essentially you look at the list and if it's on the list, it's falsy and if it's not on the list, it must be truthy. So in our case, if that was our list, let's scroll down now. If in our case the question that we now ask is, let me scroll so I leave the list visible for you, in our case is a truthy or falsy? Truthy. Because it exists. Why is it truthy? Because you assigned it above. Not because I assigned it above, but because of what value it currently has, okay? The value in a is the value 10. Is the value 10 on the falsy list? No. So if it's not on the falsy list, it has to be conceptually on the truthy list and all we need to know for now is that a falsy value becomes false when it asks to be a Boolean and a truthy value becomes true. So if I said if a, then a becomes true and the if statement executes. Now what if a was 0? What would happen? The 0 value is a falsy value so it would result in false and the if statement would say, if false, no, not going to do it. So it makes a conditional decision based upon whether the expression you give it is true or false. So could a person say if a = false? You could compare it directly to the true or the false value like that or like that. I don't recommend it. There are lots of nuanced reasons why I don't recommend it; we won't go into those weeds. There's a question in the chat room about void 0. So void is an operator. It's not very commonly used, but it is an operator that everything that you give it after the void becomes undefined. So if I said void 42, if you try that expression in your browser, everybody try it. Go to your console. Void 42 gives us undefined. So no matter what you pass to void, you get undefined back, which means void 0 also gives you undefined back.
-
Loops
Conditionals are how you make decisions in programs and they're incredibly important. They show up in more places than just the if statement. The if statement is the most common place that you see a conditional, but there are other places that conditionals are used. For example, I mentioned earlier loops, like the while loop. The while loop tests this as a conditional the same way an if statement does and it tests it every time. It's going to keep repeating itself until the thing tests false. So this brings us now into a discussion of loops and here is one of those places where when I describe to you what a loop does, it may be slightly conceptually different than what you've thought of before. So a lot of people intuit that a loop does something like if I say while a is greater than 10, a lot of people interpret this as saying that it is while the thing, or let me try to figure out how to say this. When the thing becomes false, stop doing it, or another way of looking at is, while the thing is true, keep doing it, and those two conceptual ways, that's two different sides of the same coin. The end result is the same, but the way you think about it could actually be different, depending on the different loop forms that you try, so there's a loop form called the for loop and this is a highly compressed loop and I'm going to show you the version. It's a highly compressed syntax form. I'm going to show you the three parts to how the for loop works, but then I'm going to show you conceptually how the for loop works. So this for loop, I can have a thing like a = 5. That first clause, this first expression is what we call the initialization expression. The second clause in a for loop is what we call the conditional expression or the test expression. So a less than 10. Every time I run the loop I'm going to do that conditional and if that conditional is still true, I'm going to keep going and if it's no longer true, I'm going to stop. The third and final clause in a for loop declaration is what we call the update clause. So I can say, I can say something like a = a + 1, which is to say increment it by 1 each time. A lot of people shorten a = a + 1 to this shorthand operator in the ++ operator. It's going to accomplish the same goal here. It's going to update a or it's going to increment a by 1 each time. I'll leave it in the more verbose form just so we don't lose track. So if I make that for loop, let's think about what it's going to do. It's going to start a at the value 5 and each time the loop finishes it's going to update a by 1 and if a is still less than 10, it's going to do the loop again and again and again. So if the statement inside of here was a console.log statement, try that. Try putting that into your browser, into your console. You'll notice that I printed out the value 5, the value 6, the value 7, the value 8, and the value 9, but I didn't print out the value 10 and the reason I didn't is that when a got to 10, that is after this loop iteration, I updated the a value by adding 1 to it and when I did that, a became 10; is 10 less than 10? Clearly no. So that's when we stopped the loop. Try to let that set in for a moment. Essentially we were waiting for something to tell us when to stop the loop and the thing that told us when to stop the loop is when a got too big. Yes? You said that a = a + 1 is like the update something? It's called the update clause, yes. Okay, what are the other two clauses? The first one is called the initialization clause. The second one is called the test clause or the conditional clause. And the third one is called the update clause. In for loops, all three of these clauses are optional; that is you can have all three or any combination of two of them, or just one of them or none of them. In other words, you could write, although it would be silly, you could write 4 and then put a block on it, and leave those clauses out. You wouldn't do any initialization. You wouldn't do any testing and you wouldn't do any updating. It would still run. In this case this is a loop that's going to run forever. Why is it going to run forever? This is the major conceptual observation I want to make out of this section. Why would this loop run forever? The condition will never be met. It's because the conditional would never fail, that's why, okay? So this loop is not running because a conditional always stays true. It's running forever because there's never a conditional that fails. Let me say that again. This loop would run forever, but it doesn't run forever because a conditional is always true. Like for example, if my test was the value true. This one is going to run forever because the condition is always, always, always true, right? This one, there is no condition and it's still going to run forever. So why does it run forever? Conceptually the reason it runs forever is because there is no conditional that fails that tells it to stop running, okay? This is different than how almost all developers that I come across think about what a loop really means. So what I want to illustrate is that this loop compared to this loop, the difference is that we filled in a clause here that can fail. It doesn't have to fail. What would happen if I said a = 6? Would this loop run forever? Yes. Of course. It would run forever because the first time we would run it we would set it to 6 and we'd print out 6 and then we'd add 1 to it and then we'd say is 7 less than 10? Of course it is, so we'd run the loop again, which sets a back to 6 and we'd print 6 again, update it to 7, 7 less than 10 and we'd just keep going forever and forever, so this loop would run forever, because there is no way for this to ever fail. We're forcibly making it so that thing can't fail. So that loop that I've written there, if we're trying to think about the conceptual of what a loop means, I think it's more appropriate not to say a loop runs why something is true. I think it's more appropriate to say a loop runs until something is false, until something stops it from running. It's natural state is to go forever until something tells it, stop going, okay? And the way I could write that is with a while loop. A while true loop. Would that loop run forever? Unless something stopped it, that loop would run forever, right? There are ways to stop a loop, which we're going to show here in a moment, but let's conceptually think about how to make this loop that's on top, using only a while loop. So we need an initialization clause, right? So we could do that at the beginning. We could say a = 5. Then we need a test clause to let us know when to stop. So one way of writing that test clause is to invert the a less than 10. I can say if negation of a less than 10, which looks really weird and complicated. So I could say if a greater than 10. Actually the negation is greater than or equal to 10. Does everybody see why that is my condition that would let me know it's time to stop? So how do I stop a loop, the break statement? So I'm going to test to see whether or not I should stop the stop the loop and if I do want to stop the loop, I call break, which stops it immediately. If I don't want to stop the loop, what do I do next? Let's take out that a = 6 part because we don't want that there. What do we do next? We console.log(a) and what's the very last thing that we do? A = a + 1. We do the update clause. This conceptually is how a for loop actually works and it's really how all loops work. They work until, they run until something tells them to stop running. Now I am not endorsing writing your loops like that. That loop is more complicated to understand if you already understand how loops work. The only thing that I'm doing here is to illustrate to you the concept that a loop runs until something stops it from running. There are lots of ways to make a loop stop running. You can throw an error, you can break, you can call continue to an outside label. There are lots of ways to stop a loop from running, but however you stop a loop from running, that's the same thing as the test failing. Can a person put a semicolon on the end of the incremental? You're not supposed to. Okay. It's not allowed. So once you learn the concept of what it looks like on lines 5 through 12, now writing the for loop in a more compact fashion is much more attractive. I think the thing that I'm trying to get across here is that a lot of people skip to writing these loops with for loop syntax without understanding how it actually works and then you run into off by 1 errors and all kinds of other things like that. So I think it's better to start by thinking about the concepts as expressed here because they illustrate what to do with the for loop. What do we do first? We say a = 5. What do we do next? We start running and we're going to keep going forever so that's the while true. What do we do next? We check to see if this is false, which is another way of inverting it. We can say a greater than or equal to 10. If it's false then we stop, we don't do the loop. If it's true, we keep going, we do the loop body, and finally after the loop is successfully processed through, then we update.
-
Functions
A function is a way to logically group a piece of code together, kind of like a block is, but a function also makes that block of code something that you can call more than once, so it's kind of like a loop and it's kind of like a block, but it's not going to run forever like a loop does and it's not going to run only once right now like a regular block does, so it's kind of a third different concept here. It's like putting a set of stuff into this special location and being able to say, as many times as I need it I can just call out to that stuff and it'll run. I might need it once, I might need it five times, I might need to do it over and over and over again. It doesn't really matter. We use the function to sort of logically group a set of tasks together. So I have kind of a silly running example in the book. If you've read any of the book, I have this silly example of the phone store where you're purchasing a phone or whatever, so if you haven't read it then you can go back and understand what I'm talking about, but here in this running silly example, I have the phone store employee doesn't want to calculate all of the taxes for your final purchase amount and you're talking to her and you're saying, I want to buy this phone and this accessory or whatever. She doesn't want to redo that on her calculator every time. That's a set of tasks that's repetitive that's going to need to happen for pretty much every customer that buys something and so there is almost certainly a program that does that for her. It's a checkout program. She can swipe your credit card. It automatically calculates how much to charge and all of that and that's conceptually the same thing as a function. It's taking a specific set of tasks and putting it into a thing that I can repeat on demand. Whenever I want it I can just invoke it and say do that set of things and it'll just happen, okay? So the example that we see here is I have a variable that I'm declaring with the value 99.99; that's the price of a phone and I want to print the amount. I could've put a console.log statement here, right? I could've said console.log amount and it would've printed it and then I said amount = amount * 2 which doubles the value and then I could've put another console.log, but as soon as I did that twice, as soon as I typed the same thing twice into a program, I might start to ask myself why am I repeating myself? Could I take that set of statements that I repeated and put that into a location and give that location a special name and whenever I want that stuff to happen, just call it by name. That's a function is doing. So what is my set of statements? It's just one statement in this case, but it's slightly more complex than just calling console.log amount. You'll notice that I'm also saying toFixed. Now toFixed is a method that's available to all numbers in JavaScript and it essentially formats them as a string with a certain number of decimal places on it, kind of like dollars, U.S. dollars. So if I wanted to take the number 99.99 or the number 199.98 and make it into a string that absolutely had exactly two digits, then I could use the toFixed. Let me illustrate. What if I had the number 3.141519, I can't remember; that's all I remember, 1415926 or something like, right? So that's the first several digits of pi. You notice I didn't win any pi digit memory contests as a kid. Okay, that's the first several digits of pi, but what if I wanted to print out that, let's assign that to some variable, so let's assign it to a. What if I wanted to print out that value, but only to two decimal places, or let's actually say to three decimal places? Well, I could say a.toFixed(3) and you'll notice that I'm not going to get a number, I'm now going to get a string. The string 3.142. So we rounded that digit. We rounded it by the fourth digit. We rounded that third digit up to 2. So toFixed is a way to get a number to a particular precision, to a particular number of decimal places. It's nice and helpful. I almost always use this. The only place I hardly ever use it is for printing out dollars and cents because another observation that we could make is what if I had the variable a = 3.5 and I wanted to print that out as dollars? Well, it's missing a 0 on the end, right? If I just said console.log(a) and I only get 3.5, which isn't as friendly for U.S. dollars. So if I said console.log(a).toFixed and I said give me two decimal places, you notice I get 3.50. So that's how I typically use it is I use it to format U.S. dollars. But that printAmount function is a utility that I can repeat multiple times and imagine how much more useful it would be if instead of just one statement if I had 3 or 4 or 10 or 20 or 100 statements that were logically connected together. If it took five different things to do to print out my amount, I would put all five of those in a function and then I would only be repeating the function call rather than repeating all of its contents over and over again. So that's our primary benefit to a function is being able to take a block of statements and collect it together into a repeatable, sort of named label, if you will. So a little 60-second homework. Declare yourself a function. Put a couple of statements in it, whatever statements you want like assignment statements or whatever and repeat it a couple of times in your console. You might have called your function foo like I'm in the habit of doing and that might take a = a * 2 and a = a + 3. So I'm going to multiply it by 2 and then add 3 to it. Those are my two statements. Now if I start off with an a = 10 and I call foo once and then I console.log(a), what would I be expecting the output of this to be? Hopefully you're awake enough to do some basic math here. A starts out as 10. The first time I call foo it's going to say 10 * 2, so now a is going to be 20 and then we're going to add 3 to it, so now a is going to be equal to 23, so we'd expect it to print out the value 23. Now if I call foo two more times and then I print out a again, I'll spare you the mental acrobatics. Let's just run it and let's see what happens. So we know this one is going to print out 23. This next one, what's it going to print out? 101. So it was 23 * 3 which was 46 + 3 was 49 and then 49 * 2 is 98 + 3 is 101. Question? The question was about putting our functions before our variables, like did it matter if I did that or I did that? No difference to JavaScript. It goes back to that topic that we kind of skirted by earlier, the topic of hoisting, the topic of lexical scope. Scope and Closures book covers it in depth. The Advanced JavaScript training covers it in depth, but for our purposes, you can put declarations in any place in your program. I typically put all of my declarations at the top of my programs. I put all my functions at the top and then I put all of my variables; that's my preferred style, but as long as all your variables are at the top, you won't have any surprises. I mean, as long as all your declarations are at the top you won't have any surprises. If you consistently do that it makes it easier to maintain the program later. That's generally a good rule to have a consistent style whatever it is. If your style is to put your functions at the bottom and your variables at the top, that's fine, but it's a good idea to always be consistent with that in your program. Okay, now functions can also receive what are called parameters. So here you notice I didn't receive any parameter, but what if I received a parameter? If I had a parameter called b that becomes a variable that's accessible to me inside of the function. So I could take this value right here and instead of it being the literal value 3, I could have it be the variable b. So when I run this function now, it's behavior is partially dependent on what value I pass in. Does everybody see that? If I pass in a different value of b, I get a different result out. Let's try it. If I start out with a = 10 and I say foo(3) and then I say console.log(a), what are we expecting? The same thing as before, we'd expect 23, right? A went from 10 to 20 and then we added 3 to it and it became 20, but what happens if I put in 100 here? Now we're expecting 120. Does everybody see that? So what I pass into my function changes its behavior because there's a parameter that I'm passing in. By the way, a little nuance. It's not a big deal, but terminology is, I mean I think if you're learning things it's important to learn correct terminology. When we call the function here, we are passing in what's called an argument. So you can have one more arguments that you pass into a function, but when we declare the function and we have these names, like I can say b and bar and zaz and whatever. These variables here are called parameters. So in other words, there's a match, a one to one match between and argument that gets passed in and the parameter in that position. A lot of people use arguments and parameters interchangeably as meaning the same thing because they get assigned to each other so it seems like they could be considered the same thing. To be completely specific on terminology, it's an argument when you pass it in, it's a parameter when you declare it. So this parameter b that we've got, got assigned the argument 100 and then we used that parameter as a variable and we printed it out. So let's try this again. If I said foo(5) and foo(25) and foo(100). So I called foo three different times with three different variables, all accumulating my results into this a, what's my end result going to be? My end result, the suspense is killing me, 250. Is there a question? Asking about passing a function as a parameter with another function? So yes, you can and then the next question that was asked might be slightly, or the next answer that was given might be slightly misleading, so let me just quickly divert into that. If I called foo, let's say I had two different functions here and it doesn't matter what's in bar right now. If I said foo and I gave it the name bar, I passed in bar, what I'm doing is getting the value that is currently in bar. What is the value that is currently in bar? It's a function. It's a function value. So I'm passing the function as an argument and it's getting assigned to the parameter b. So if I said + b here, what is b? B is a function which, that's not really what we want. We wanted the thing to be called. I could call it here and whatever it returned, I'd get that value, but if you pass a function as a value, it's just a function. If you call it, then what it returns is what gets passed in as the argument. So there's the difference between passing a function and passing the result of a function call. So hopefully that clears up the questions that were happening, that were being asked in the chat room. Okay. Oh, one last detail on this function, let me back up. One last detail on those functions. These functions can return values as well. They can pass in values, they can return values. So if I said return a / 2. If I say var 2 = 10 and I call foo with 3, we know a is going to become what? It's 23, right? But what if we took that return value and assigned it to another variable? You see when I invoke foo it's going to run, but then it's going to return me a different value. In this case it's going to compute 23 / 2, which is? 11.5. So 11.5 is the thing that's going to come back and get assigned into the variable b. So if I say console.log(b) I'm expecting to get 11.5. So if we take that program and put it into our console, we're expecting both 23 and 11.5 to be printed out, and in fact that's what we get. So in the second example, what does it do with variable a? Is the variable a left alone? Here we're not assigning to anything, we're computing something and returning it. Here we are assigning, so we're making changes to a variable. We're actually having outside side effects on that.
-
Scope
Can I give a default value to the parameter? In JavaScript ES6, that's the coming version of JavaScript, we do have a syntax for default parameter values. That doesn't exist in your current JavaScript, but the next version has it. And do you have another course on that? There is a course on ES6. They're asking about a function callback button. That's more than we'll get into right now. We'll probably come back to that after lunch, but that's more than we'll get into now. What I want to do in our last couple of minutes is talk about the difference between this variable a which exists outside of the function and this variable b, which exists only inside of the function. You'll notice I have another variable called b here. These b's are entirely different. Does everybody see that? There's a variable b, it's almost like there was a var here, there isn't, but it's almost like there was a var here. That declared a b that exists only inside of that function. So if I took this part out and I just tried to access b, what we expect to have happen is an error because there is no b available to line 9. The b exists only inside of the function, not outside of it. Identically to if I said var c = 42, if I put a variable inside of my function, it's not available outside and if I said var c, if I take that program and I run it, we're going to expect to get a reference error because c doesn't exist and in fact we get reference error c is not defined. Okay? So putting a variable outside versus inside a function changes where it is scoped. Scope is this technical term for, you can think of it as sort of like there's a bubble around the internal contents of foo and then there's another bubble around the outer contents of our whole program. Those are two different scopes. There's one scope here and one scope here. Notice that there's no a inside of our foo and yet we didn't get a problem and the reason for that is that you can always access variables above you our outside of your scope, but you can never reference variables that are further down, so that's a one-way street. When I ask for a here, it first looks to see if it sees an a inside of foo, but it doesn't and so where it goes next is it goes out one level of scope and it finds an a there, so it's able to use it. But the reverse was not true. We could not take a variable that was inside of it and access it from the outside.
-
Challenge 1
I mentioned before our break there is this practice section at the bottom of chapter 1 and essentially it's building on that metaphor that this whole chapter goes through, asking you to write a program to calculate the total price of your phone purchase or whatever. I'm not going to bore you by repeating this, but I will point you specifically to this section of description there including also the bonus challenge if you'd like and what I'm going to do here is suggest that you try that before scrolling down and looking at how I did it and that may feel a little uncomfortable to you, especially if you're slightly more on the beginner side of this, but just try. There is more value in the attempt than there is in the successful completion of something, so just try to take what I've described here and construct a program based upon what you've learned and there are hints in terms of you'll want a use a variable here or you'll want to use a function there. And so what I'm going to do is essentially stop talking for a little bit and I'll probably give about 5 or 10 minutes here for you to work on this practice exercise, available for questions either for those of you online or for those of you here in the class. I expect that there will be several questions and if I need to come back and address something to everyone, we'll break back in and address it to everyone, but we're going to actively work on this exercise and I'm going to encourage you to try it. It's a big enough exercise, not big, it's like 20 lines of code, but it's a big enough exercise that I'm going to encourage you to write it in a code editor like I've been doing, write something in a code editor like Sublime or a text file or whatever you want to do and then copy and paste that into a console to run it rather than trying to write yourself in the console because it's very easy to be on four or five lines of code and your console is very easy to get mixed up and accidentally hit Enter too early or something. So I encourage you to try it in a code editor and so we'll take some time to work on the exercise and if there are questions, let me know, but definitely read through this sort of description. Your goal is essentially to write a program that simulates parts of purchasing a phone and calculating the price and so forth. So go for that and let me know if you have questions.
-
Challenge 1 Solution
One of the items stated that we wanted to set ourselves up a few variables and I indicated that some of them should be constants. If you have the advantage of using ES6, which is at the moment going to require using a transpiler. It's a tool that converts your code so it will run in browsers, so it's possible to do and a lot of people are doing it. I'd encourage it if you're writing JavaScript, but it might be slightly overkill for what we're talking about, so either a var here or a const if you were using ES6 would've worked. If we put a var here instead of a const, the only difference is we're not going to get an error if we were to accidentally change the variable, but by convention if you say var and you have an uppercase variable like that, by convention, people know don't ever assign to a thing, so it's sort of, it's the difference between a convention that signals what you want versus the language actually enforcing it. So even without the enforcement we can still get a long way, so you could have taken these as vars. Of course, my bank balance is something that you would typically think of as changing. The biggest reason why I make this a variable instead of a constant, it's a constant for the purposes of our program, that is that we don't change our bank balance, but the biggest reason why I'd make it a variable is because it might be the kind of thing that you'd want to prompt a user for. So if you were going to try the prompting you would want to do it and it's an important note by the way that constants have to have an assignment, so you can't say something like, if you're doing a real const. You can't say something like const foo because it doesn't have an assignment and it could never be given an assignment. So there has to be an explicit thing that's getting assigned to it. Alright, so here's my bank balance that would be considered a variable. Now my amount is going to be kind of my running total, if you will, of how much I've spent. We'll come back to the functions in a minute, but the main meat of what I want to do is I want to loop through as I hinted in that description; I want to loop through and keep doing something for as long as I'm able to do it so basically I'm figuring out what my purchase amount is and I am being somewhat irresponsible. I'm just going to keep spending until I don't have any more in my bank account, right? So here I'm going to say while the amount is less than my bank balance, okay? So amount = amount = phone price is buying a new phone and you notice my usage of comments here. In this comment I didn't say add the phone price to my current amount because that would be repeating what the code already said. This was more a why or a how kind of an explanation or sort of meta explanation, so I'm indicating here that you're buying a new phone. Now we want to know if we can afford the accessory. I indicated in that problem statement that you would want to be able to purchase an accessory like an extra charger or whatever. You'd want to purchase the phone accessory for each phone, assuming that you haven't gone over a certain threshold of your spending limit. So we had a threshold that we declared is $200 and after that we might buy phones, but we wouldn't buy any more accessories, okay? So just a simple little expression in code of how we might be thinking about things in our mind, so as long as the running total amount is less than our spending threshold, we do want to add in the accessory price, otherwise we would just keep going until the amount was not, until the amount went greater than the bank balance. Now, amount, we don't want to forget to pay the government so we now say amount is equal to amount plus and here I can call a function. I say calculate tax. So that's a set of things that I might do only once or I might do multiple times. In this program I'm oinly doing it once, but there is still value in putting it in a function because this code is more understandable than if I dropped that same code directly in here because the name of the function explains something about what I'm doing. I'm taking advantage of the fact that I can name this function something like calculate tax, whereas if I took just amount times 1.8 or whatever I did, that would look less reasonable or it would make less sense. So another virtue of using functions is that you could put in a name for that section of code that makes the code more understandable. So our calculate tax, we take in an amount and we multiply it by the tax rate, so tax rate being set up as .08, so this tax amount is just the tax, you know the $12 or $8, whatever it would end up being, and we add that to our existing amount and now we then say your purchase amount, so this is like the cash register, your purchase amount, and I call format amount and the reason for that is I want it to print out a nicely printed U.S. dollar figure. So we're going to put the dollar symbol in front of it and then we want to call that toFixed method to round it to a certain number of decimal places. So I'm calling that format amount and then finally as kind of an extra little flourish here, I would ask, did I go over my bank balance and if I did, I'm going to print out, oh you can't afford this. Now the way I've set up the program, of course I've gone over my bank balance because I didn't stop until I already went over it and then I had to add tax on, okay? So thankfully I am preventing myself from completely running my bank account down to zero, but that just illustrates some of these concepts that we talked about. You can see that there are conditionals to help us make a decision; should we do something or not. In this case the decision is whether or not we print something. Here the conditional is whether or not we do something extra inside of this loop that's happening. Here the conditional is deciding if it's time to stop the loop or if we should keep going. These functions are things that we can call one or many times. They're a collection of things, we can pass values in as we are doing. We can pass arguments in that get set to these parameters. We can also take advantage of return values to return things out. You'll notice that these two functions don't make any changes to the variables outside of them and that's actually an intentional design decision on my part. Rather than me saying in here, instead of saying return, I could've said something like amount = amount + the tax right, right? I could have done that, but if I'd done it way I'd be making what's called a side effect of a function call, which would work. We saw several examples of that earlier with the foo and bar functions, but it's typically considered to be a less graceful form of programming for your functions to have those side effects. You typically will think about a function as being entirely self-contained. You pass in a value or multiple values if you need to. You get one return value out and everything that happens inside of the function is sort of self-contained and you don't make any changes outside and you try not to rely upon stuff outside of the function as well, although there are cases where it's inconvenient to pass in everything, so these are not hard and fast rules, but just stylistically you just typically want to design your functions to have as little impact to the outside world as possible. There's one big caveat to that, which is not a topic that we're going to go heavily into right now, but there is one caveat to that and that's the caveat that closure is when you intentionally want for a function to remember stuff outside so that it can keep track of its state. So there is a design style or a feature in JavaScript called closure and we intentionally do that sort of stuff and I cover that in basic detail in chapter 2 of the book, so you can go further from this class and read about a basic expression of how closure works in chapter 2 and I also have a full book about closure, the Scope and Closures book is really kind of all about that, so there's plenty more to go if you want to learn more about how that works. We definitely won't worry too much about it, but there are places, just suffice it to say, there are places where you intentionally do decide to have a function rely on outside variables. Yes, let's see, the question is, should a function always return a value even if you don't have return in the function? Functions only return an explicit value if you actually say return, normal functions that is. If you call a function and you do not have a return, it sort of implies that there's a return undefined at the end, but there's always a result from a function call as either that implied undefined or whatever you explicitly return, and the question of should a function always return, there are many functions that I write that it doesn't make sense for them to have return values. So there is no should it have a return or not. It should have a return if that makes sense. In this case it makes sense for both of my functions to compute something and return a value. Sometimes you just have a function doing something. That's a function that maybe has a side effect like it's calling something or whatever. So there are plenty of places where return values don't make sense. And the next question was in the program, the amount is always going to be greater than the bank account so both the console logs will be printed, why are we doing it? It's just a simple demo. I wanted to show you that there's a way to decide whether we are looping. We could've been more nuanced about it and said, while amount is less than bank balance minus threshold or something like, we could've said I want to spend until I have, you know, until I've spent to where my threshold is under $100 left in my bank account. We could've done it that way, of course, but the point here was just to illustrate the different ways that conditionals can be woven together in our program. The next question, why are you returning amount.toFixed if you make purchase more than 1K or 100, I guess you meant, how the amount will be printed? Oh, so it's important to understand toFixed(2). That indicates decimal places, not digits in your number. So this only means that I want to round and pad my decimals to two decimal places. The amount on the left-hand side, if I'd gone all the way up to $5000 or $5 million or whatever, we can have as many digits on the left hand side. There's another method called toPrecision if you want to actually restrict the number of digits that show up in a number. For those of you that science classes you'll know about the difference between precision and not so. There's a toPrecision method that can be used for that purpose, but here toFixed is only dealing with the number of decimal places that we get out.
-
ECMAScript 6
When will it become standard to use const? It's already a standard in the sense that ES6 has already been officially voted upon and so const is happening. I mean, there's one last official vote that will happen in June of this year to kind of give it the final stamp of approval, but it's a virtual certainty ES6 will happen as the standard is already written and there are several browsers that are already so the new versions of Chrome, Firefox, IE, they all support it. If you're having to run code that's running in older browsers or you're trying to use ES6 features that don't yet exist even in the newest nightlies of browsers because there are some unimplemented features as of yet. If you're trying to do that the bridge is to use what's called a transpiler. It's a special kind of compiler that takes your existing JavaScript code. Say you write code that has ES6 features in it and it converts that code to something that will run the same way but in older browsers. So it goes through lots of different tricks to figure that out, so we won't belabor that point, but I'll just quickly illustrate that if we had, there's a tool called Babble that is probably one of the more common transpilers and if we had some code in Babble, let me try to zoom in so it's a little bit more readable. If we had some code in Babble that we were trying to play around with and see what's the equivalent if I wrote in ES6, what's the equivalent of it in something that runs in a browser? So if I say const x = 10, you'll notice over here that they're not actually doing const. The thing that they're transpiling it to is this other stuff where they're setting up different checks on its behavior so that's going to behave almost identically to the way const will work in a normal ES6 engine. So this is the code that's automatically produced by this tool and that's the code that you would sort of compile and ship out to the browser while you would maintain your source code and your repository or whatever would use the const. So you would author in ES6 and as a build step you would transpile to something lower and ship that out. So this is a pretty common practice among JavaScript developers and applications and it's becoming even more so. This is kind of the new norm is that you're going to be, it's going to be suggested that you do always write in the newest version of JavaScript and if you have to run your code in older browsers which is the reality for most of us, you just simply let a build set up with this tool take care of the implementation details. So we won't go into any more details about how Babble works or what it does, but it's a very sophisticated program that's able to figure all that stuff out for us, and kind of let us not have to worry about it. So basically the takeaway here, you should if you're going to take seriously writing JavaScript, if you're going to work in an environment, write in an application, if that's your job, I'd recommend switching to ES6 now which is going to take learning ES6, so there's plenty of work to do there, but once you've learned it and implemented it, you just need a build step with a transpiler like Babble or something like that to take care of the compilation, okay? So did I miss any more questions? Yes, Babble does have a lot of great examples. There is more than just Babble. I'm not meaning to say that's the only tool. There's Tracer and a couple of other ones, but Babble is one of the more popular ones these days so it'd be a good place to start. Yes, it was mentioned in the chat. I just want to make sure everybody sees. There are tools, if you're not really serious about like a full build step thing, but you just want to play around with how ES6 works, there are tools like ES6 Fiddle.NET and what this tool does is it does the transpiling and the compiling behind the scenes so it'll just run your code. So if I said something like const x = 10 and then I said console.log(x) and then I said x = 20 and console.log(x), the question is, am I going to get 10 and 20 or what's going to happen and the way it's going to do is it's going to transpile that const so that this state is not allowed and you'll notice that we get an error. It's saying x is read only. So it's transpiled under the scenes so that I wasn't allowed to do line 5. So you can play around with various different ES6 features here and they've got several built-in examples, so if you wanted to learn. Somebody asked earlier, how do I do default parameters? Well, here's the syntax for default parameters as of ES6. You just put an = sign and the value to assign a default parameter. So you can play around with those if you're interested in learning more about ES6 and as a reminder, there is definitely and ES6 course available from Frontend Masters.