What do you want to learn? Leverged jhuang@tampa.cgsinc.com Skip to main content Pluralsight uses cookies.Learn more about your privacy JavaScript Best Practices by Jonathan Mills Identify and prevent common problems and headaches in JavaScript by learning best practices. From syntax oddities, to async patterns, to callbacks, this course will help you walk through how to deal with some of JavaScript's problem spots. Resume CourseBookmarkAdd to Channel Table of contents Description Transcript Exercise files Discussion Recommended Course Overview Course Overview Hey everyone. My name's Jonathan Mills and welcome to my course to JavaScript Best Practices. As a consultant, I get to work with companies who are trying to adopt to the current stack of JavaScript technology such as angular or no-js. And in this course, we're going to talk about some of the struggles that developers run into when they start writing JavaScript. So in this course, what we want to do is look at some of the best practices around JavaScript. And instead of just telling you, "here's what you need to do." We're going to take the time and I'll walk you through why you need to do the things that we're talking about. So we're going to approach this conversation from a couple of different directions. The first one being, we're going to talk about syntax best practices. And we're going to talk about things like semi colons and IIFEs and curly braces and those types of things to make sure that the code we write is being written in a way that makes sense. The next thing we're going to talk about is more behavioral, the way JavaScript behaves. And we're going to talk about the vis keyword or strict mode and what strict mode actually does. Then we're going to move into more structural components like callbacks and promises and the module pattern and things like that. So that we understand, not just the syntax that we write, but the bigger concepts of what we're trying to write when we write code. And we're going to end this conversation looking at mostly the server-side and how to set up no-js applications to be successful in a production environment. So by the end of this course, hopefully you would have picked up some tips on how to not only how to write better JavaScript but also have a clear understanding of why JavaScript is behaving the way it does in your code. Why Best Practices? Introduction Now a conversation about best practices can sometimes be a little painful for everybody involved because the term best is nebulous at best and just wrong at worst and so what I want to do is I want to spend some time in this first module talking about why we need or why we should discuss some best practices and kind of the approach we're going to take when we do it. Now, I've noticed over the years that JavaScript is traditionally a secondary language for a lot of developers. They operate most of their lives in C-sharp or Java or Ruby or something else and then they use JavaScript to make their browsers work and a lot of their time and effort is spent on being very, very good at a language other than JavaScript with very little time being spent on the JavaScript side of your job. Now that's changing with the rise of single-page applications that have come about to make this very rich browser applications that more and more of our customers are starting to expect and we're starting to spend more and more of our time on the JavaScript side to where JavaScript is almost becoming the primary language and the other languages are almost secondary for just serving up our APIs or something like that and with the rise of node, JavaScript's taking over the server and we've got now mobile frameworks like React Native that are taking over our mobile development as well. So JavaScript is starting to be everywhere in what we do. On top of that, JavaScript's just different, it just is. It's different than the other languages that we work on and sometimes that's really good and sometimes that's really, really bad and so what I want to do is I want to spend some time talking about why we need to look at some of the things that are different about JavaScript and then go into what the differences are and the best way to understand what's going on inside JavaScript Don't Code in a Vacuum The coolest part about trying to get better at JavaScript is that we're not living in a vacuum. We're not on our own trying to figure out the best way to do something, there's a lot of people who've been out on the forefront of JavaScript who've already worked through a lot of the struggles already and so that means that we can leverage their experience in order to make our cout better. The other side of that coin is that sometimes we're inundated with suggestions and the right way to do things on the Internet with very little filter, which is why we end up with a lot of conflicting advice or somebody saying you should use semicolons and somebody else saying semicolons are evil and that's one example of raging debates in the JavaScript world about the best way to do something. So in that situation, sometimes it's dangerous just to go out and plow through some websites and say, "Hey, what are people saying that we should do?" What I want to do in this course is arm you with some knowledge and filter some of these debates that are out there and help you understand why JavaScript works the way it does so that you can work through all of these conflicting pieces of advice and understand where the argument really is and what the best way for you to write JavaScript code. Write Code in a Maintainable Way Now one of the fun things about dealing with JavaScript is its weird approach to syntax and it's different, I mean it legitimately is different and not always makes sense. So one of the things we have to dig into are the weird idiosyncrasies around JavaScript syntax, things like why would this be true, an integer 10 and a string 10, they're the same thing so that's weird. And why won't this work? If you run this, this will not work. You're not going to get your object literal back. So one of the things the struggles with dealing with JavaScript sometimes is we get these weird, obscure errors that when you just look at the code, you might look over why that's broken and not understand what's going on here and so one of the things we're going to try and work through is how to prevent that .01% of issues. If you've ever spent three hours tracking down an issue only to find out that semicolon insertion did something you didn't expect or you forgot to execute your IFFE statement or things like that, we're going to try and find a way to prevent this .01% of errors from happening. Another aspect of this conversation is to dig into a little bit of what the JavaScript runtime is doing and things like "this," the "this" keyword is one of the most misunderstood and confusing aspects of how we program JavaScript and so what we'll do is dig into "this" and what "this" is and all these other behavioral things that JavaScript does such as strict mode, what's the difference between strict mode and not strict mode, what is a closure and how should I use closures and those types of things. When we get into the behavior of the JavaScript runtime and the JavaScript compiler, we'll talk about how to best approach some of those situations. Also, nothing's as bad as yesterday's code. I can't count the number of times I've looked back at code I wrote a week ago, a month ago, or a year ago and think how horrible that code is and how if I wrote it now I would do things so much differently than I did back then. Or there are times when you look at your code that you wrote just a month ago and have no idea what you were trying to accomplish. You know what you were doing at the time, but now a month later it's difficult to understand what your code was doing or what you were trying to accomplish and what I want to get out of this conversation is how to write your code in a more maintainable way so that six months from now you can still understand what you're doing and what the flow of your code was as you're going. When you write code, the way a lot of JavaScript developers write it by just throwing spaghetti at the wall and see what works, then sometimes a week later or sometimes even four hours later, it's hard to go back and remember what was the problem you were trying to solve and why didn't you write it in just an easier way. So we'll talk about that quite a bit. The other thing to remember is we don't write code in a vacuum. Most of us, the vast majority of people watching this video, work with other people and there's nothing as bad as someone else's code. Your code may be bad, but their code's worse and sometimes when we're looking at other people's code or we're writing code for other people to look at, more importantly 'cause we can only control ourselves, we want to make sure we're abiding by standard practices and standard principles so that when somebody else picks up our code, then they can easily understand what we're doing and have a common vocabulary that everybody speaks so that everybody can easily maintain each other's code. The cool thing about the time we live in, as I said before, is that we're not working in a vacuum. There's lots of developers out there who are fighting all the same battles that you are and just a quick look at GitHub shows a ridiculous number of JavaScript packages that are available for us to use. There's things like ESLint that we'll talk about later, there's React, there's an ES6 cheat sheet, there's Express, there's all these packages and frameworks out there that we can use to make our lives so much easier when it comes to building our JavaScript code and so one of the things I want to get out of this is I want to work through which of these packages we're supposed to be using, what packages should make our lives easier and what packages are going to make us ready for the next versions of JavaScript as well. So we'll talk a little bit about how to make your life easier by picking the right packages that are available to us so that we're not reinventing the wheel all the time. So in addition to packages that are available that we can inject into our code, there's also a really robust tool set that's been built out around JavaScript and so one of the things we're going to talk about are the tools that are available. For each piece of this puzzle as we go through this code, as we go through this course, we'll talk about tools that are available to us to help us make our code better and automate as much as we can so that we're not constantly having to do things by hand. If we can automate something let's get that thing automated. Rules of the Road So here's just a quick recap of what it is we're trying to accomplish as we go through this. The reality is best practices is a vague term at best and can be a little bit misleading in its intent. So really what we're going to do as we talk about best practices, we're going to talk about the why behind the best practices. We're going to look at the behaviors and the things that JavaScript does or the things that we do in JavaScript so that we understand why we have an issue that needs to be solved with a best practice and then you can decide for yourself and for your environment which of these best practices makes sense and which of them don't. Once you're armed with the knowledge and the information about why things work the way they do, then it can be up to you to decide what the best way to go about writing JavaScript is for your environment. Syntax Introduction Alright so we're going to kick this course off with a conversation about syntax and before you tune out, don't do that just yet, syntax in JavaScript can be sometimes a little painful because it operates a little bit differently than a lot of other languages and the struggle for a lot of people who are working in JavaScript is JavaScript is your secondary language. You spend most of your time working in a different language, .NET, Java, Ruby, whatever language you're using, and then you come over to JavaScript and sometimes we forget that JavaScript is different and it does things differently than a lot of these other languages and so what I want to do is I want to spend a little bit of time talking about syntax and what some of these differences are and we'll talk about things like semicolons and we'll get to the bottom of all of the hassle and as we talk about some of these things, I'm not just going to tell you, "Hey, here's what you do." I want to spend a little bit of time digging into how this stuff works and so when we talk about semicolons, let's talk about how they work and what automatic semicolon insertion is and all of these things. We're going to talk about linting and how to get a linter set up and how to check your code to make sure it's going to work right. We'll talk about equality and equality's a little bit different in JavaScript than it is in other languages. JavaScript sometimes tries to help us and sometimes if we don't know that it's going to try and help us, it's a little bit painful and we'll talk about things like variables, we'll talk about how to declare variables, which may sound weird, but when you declare a variable in JavaScript, some different things happen than you might expect and so we're going to talk about what that is and what that looks like and then we're going to end with a conversation about functions that's going to pull in our conversation about variables. So just spend a little bit of time working through this stuff with me and get to the bottom of why we do some things differently in JavaScript and why JavaScript works a little bit differently when it comes to the syntax and how things work. Semicolons We're going to start off our discussion around syntax options in JavaScript with a conversation about semicolons and we're going to start with semicolons because this seems to be one of the most contentious syntax conversations that go on in the JavaScript community and it ranges from "You must use semicolons, they're required," to "Only an idiot would use semicolons," and it kind of goes back and forth between those two extremes and I want to take a little bit of time and really dig into this conversation because it's going to give us some insight into how the JavaScript compiler looks at tokens and lines and things like that and what's really going on with semicolons behind the scene. And so I'm going to start with this quote. I have heard this a lot and if you ever go out to Stack Overflow or some other website you'll see this comment made a lot, "Semicolons are optional in JavaScript," and I understand the intent of the statement that they are saying, but this isn't entirely correct and so let's dig into the ECMAScript Standards for just a minute and really look at what that means when that statement is made. So the section on semicolons in the ECMAScript Standards starts with this comment, "Certain ECMAScript statements "must be terminated with semicolons." Now that is a far cry from the previous quote, which was "Semicolons are optional." Well in this case, certain ECMAScript statements must be terminated with semicolons. So what's the discrepancy? Let's look at that. It goes on to say, "For convenience," translated into because we know developers are lazy, "however, such semicolons may be omitted "from the source text in certain situations." So that's an interesting discrepancy, right. The previous comment, must be terminated with semicolons, however, they can be omitted in certain situations. And so it's important to understand what those certain situations are so that we can understand what's going on behind the scenes. So it goes on to say this, "These situations are described by saying "that semicolons are automatically inserted." Now that doesn't necessarily mean that semicolons are actually inserted, it just says they're described by saying that semicolons are automatically inserted and what that comes down to if you've ever heard the phrase "automatic semicolon insertion" or ASI or any of that stuff, that's what we're talking about. And so the key to understanding semicolons is looking into what the rules are for automatic semicolon insertions when they're inserted and when they're not and then deciding whether or not those situations where they're not or are warrant you doing something around using semicolons on your own. So let's take a few minutes and dig into the rules around semicolon insertion. Automatic Semicolon Insertion Now when it comes to automatic semicolon insertion, there are three rules that the JavaScript compiler looks at when it decides whether or not it's going to insert a semicolon after a token. The first rule comes down to this. "When, as a Script or Module is parsed from left to right, "a token is encountered that is not allowed "by any production of the grammar." Alright so break this apart. When a token is encountered as a Script or Module is parsed from left to right, that is not allowed in any production of the grammar, something happened. Let's take a look at this for just a second. So the compiler's going to start with this V right here and as it processes those tokens from left to right, so V all the way down, it's going to go all the way through 12 and then it's going to hit the new line character and it's going to hit the next V. Basically what that rule meant was the V is not allowed in that context. Because the previous characters were a 12, the V doesn't make sense in that context. So therefore, this rule kicks in and when that rule kicks in, it does one of a couple of things. So the first thing it does is this. If the offending token is separated from the previous token by at least one LineTerminator. So that V is separated from the previous token by at least one LineTerminator, it's going to insert a semicolon right there. So what you're going to end up with is something that looks like this. According to rule 1a, we now have a semicolon at the end of that line because the V on the next line is not allowed, it's proceeded by a new line character. So we're going to stick the semicolon up there next to the 12. Applying that same rule, we also get a semicolon after var b = 13. So that's the first part of rule one. Really simple, pretty straightforward. The second part of rule one involves this if statement that we've got down here. So the second part of rule one kicks in if the offending token is a curly brace, a closing curly brace, and so if the offending token is a closing curly brace, then we're going to stick a semicolon before the curly brace. So let's look at that. So right here, so if A exists, we're going to console.log(a) and then a curly brace. Because this curly brace is not allowed after the closing paren and the A, rule 1b says hey let's stick a semicolon in front of the curly brace. So it sticks a semicolon right there. Really that's the first two parts of rule one and that's pretty straightforward. Let's skip ahead and let's do rule two, then we'll come back to rule one for a little bit and talk about an issue that arises. So the second rule reads like this, when the Script or Module is parsed from left to right, the end of the input stream is encountered. So basically at the end of the stream of tokens, then put a semicolon in there at the end of the stream. Pretty straightforward, pretty easy. So let's look at that one down here at the bottom, console.log(a+b), it hits the end of the stream after the parentheses. We're done. So automatic semicolon insertion will say okay, well let's stick a semicolon in there. That's all that means. That's a really long rule to basically say hey let's stick a semicolon at the end of the file. So if I stop right here, I may have convinced you that semicolons or using semicolons is kind of useless in writing JavaScript because this is all fairly obvious, hopefully nothing too earth shattering has taken place here, it inserts semicolons at all the places where you should have been typing semicolons all along. Fine, no worries. Let's go back and look at rule one for just a minute and then we'll jump down to the third rule to look at some exceptions to where some problems may arise. Now if we go back to rule one for just a minute and look again at the wording of this rule, you notice one very important thing, "a token is encountered that is not allowed "by any production of the grammar," the "not allowed" is very important because if it sees something that's not allowed, then it's going to insert a semicolon. If it is allowed, it's going to keep going. So let's look at what that means. So here we've got something that's a little bit different. Rule 1a applies to the var a = 12, the var b = 13, and then down inside my .forEach, my console.log, rule 1b, all those get semicolons. The issue is when it starts at the var c, it's going to come to the A, see a new line character, and then see this opening bracket. Now in context, that opening bracket is totally allowed because I could very well be saying A and then array notation or bracket notation on an object. So that bracket is totally allowed in this context, which means it will not put a semicolon there. So in this case when I run this, it's going to throw an error because there's a sub bracket stuff is not defined, it doesn't know what that is so then there's no .forEach on undefined. So you see what I'm saying. Now that's not necessarily a normal occurrence. We don't see that all the time and it's very easily to fix that just by sticking a semicolon after the A and then everything just works. Where you actually may run into this, or I run into this on a slightly more regular occurrence, is in this context with my IIFE syntax. So I've got a couple of variable declarations, I'm doing some stuff and then I've got an IIFE or an immediately-invoked function expression. Now when the compiler hits the A and then it moves on to the parentheses, again it's totally allowed because I could just be executing A as a function and passing in that IIFE. So it will not stick a semicolon at the end of the A. Now, most of you don't write code like this and that's totally cool. Where you run into this is when you have multiple JavaScript files. Whenever I write angular code, I wrap that in an IIFE. Almost everything I do in angular is wrapped inside of an IIFE. But not everything else is and so when I concatenate all the JavaScript files, sometimes you have a file that's not written inside an IIFE and a file that is written inside an IIFE and you end up with something that looks very much like this once the file's all concatenated and things can break because you don't have that semicolon. So that's not going to bite you very often, honestly, it just isn't, but that's one of the concerns about not using semicolons is that you'll get bitten by every once in awhile this automatic semicolon insertion is not going to insert a semicolon. There's one more rule I want to talk about that has a little bit of the opposite problem. It's going to insert a semicolon where you don't expect it to. So let's look at that real quick. Alright so the last rule in semicolon insertion comes down to this, in the ECMAScript Standards it says, "When, a token is encountered that is allowed "by some production of the grammar," so it's perfectly fine, "but the production is a restricted production," we'll talk about what that is in a second, then, to skip ahead, "the restricted token is separated "by a previous token by one LineTerminator, "then a semicolon is inserted before the restricted token." Okay, let's talk about a couple things before we dig into what all this means. First and foremost, restricted production. That's a very fancy way of saying continue, break, return, or throw. So if you have a continue statement, a break statement, a return statement, or a throw statement, that's what's called a restricted production and what happens is when you run into one of those words, according to this, if there's a LineTerminator after the restricted production, then a semicolon is automatically inserted before the restricted token, which would be the next token. So what that means, let's look at some code. Right here, I have a function that has an if statement that returns something. Now, curly braces are underneath the function. The first two curly braces, after the function and after the if statement, are fine, nothing's going to happen, however, because of the rule, rule three of semicolon insertion, return, the return statement is a restricted production, which means that since there's a new LineTerminator after the return statement, it will put a semicolon at the end of the return, which basically means this whole block right here will not be executed. When I do the return, it's going to stick a semicolon after the return and that block is not returned. So what you'll see as you put the curly brace up next to the return, we'll talk about curly braces here in just a minute, but this is a situation where the semicolon insertion is actually going to insert a semicolon where I don't necessarily want it to be and so that works in both ways and can become a little bit of an issue sometimes. Where this actually happens more often than not is if you're a .NET developer who's used to putting curly braces on the next line and then you come over and you write in JavaScript and you put your curly brace on the next line and now you've got a problem. Now, in fairness to some people, using semicolons in this situation is not going to solve that problem, right. So if I'm an adamant semicolon person and I put semicolons at the end of everything, that's not going to prevent this from becoming an issue. But there is something I do on a regular basis that helps with this and so this comes down to where I kind of sit is I do semicolons and I do semicolons in conjunction with JSHint, or you can do ESHint or JSLint or some other thing, and so I've got my same function here in brackets and we'll talk about how to set this up in just a second. Down here at the bottom, I have this little exclamation point and when I click on that, in this code it says look at this, right here number five, missing semicolon after my return statement. If I double-click on it says line five, look, I'm missing a semicolon right there. Well that's kind of dumb, I don't want a semicolon right there. But it's letting me know, hey you're going to have a semicolon there and that's not okay. So now I know I need to go back and do that and I save that. Alright, now I'm missing one other semicolon on line seven and this is not defined so that's a whole different issue and we're not going to talk about that right now. But there we go. This is now working. And so here's the thing and here's my rule. I use semicolons, so I actually do use semicolons, in conjunction with JSHint, I use JSHint, you could also use ESLint, to prevent potential issues around semicolon insertion. Now this is my rule, this is what I do for a couple of reasons. One being just consistency with other languages. So I like to get in the habit, I'm a creature of habit as are a lot of people, and one, if I'm writing .NET code or Java code and then I'm switching over to JavaScript, I do semicolons, I do semicolons everywhere. So I carry that over into my JavaScript code, whether I need to or not is fairly irrelevant at this point. I can, so I do. The other thing is that it does prevent the .01% of issues. You could probably get away with not doing semicolons and very rarely run into an issue, but occasionally you will and so the connection of using semicolons in conjunction with JSLint to let you know when semicolons may actually happen just prevents the possibility that something's going to break that you're going to then have to track down. If you've ever had to track down weird random errors after you've done concatenation and minification and now all the sudden something breaks, well chances are it's semicolon issue somewhere. So that's semicolon. Now you kind of get an idea of where I'm going to lean on a lot of things, but that's semicolons and that's my thoughts on that topic and the best practice, and I put best practice in air quotes kind of as I'm speaking, is in my opinion, use them, use JSLint. But this is you can really, now that you understand how semicolons work and how automatic semicolon insertion works, really now you're armed with all the information you need to decide for yourself and the only thing I will say is make sure you're consistent. If you're going to use semicolons sometimes, use them all the time. If you're not going to use them at all, just don't use them. And then it prevents confusion especially by other people who are going to be interacting with your code. Remember, we don't code in a vacuum so we want to add some consistency to make sure everybody else knows what's going on. Linting Now since I suggested using semicolons in conjunction with a linter, we should probably spend a couple minutes talking about linting your code and see what that means when I say that. Now, a linter scans your code to detect potential problems and errors and the keywords there are potential problems and potential errors. That doesn't mean when it says you need to do something it is an error, it just means that sometimes in some circumstances some things may break and so it helps you avoid that situation altogether and we kind of looked at that with semicolons. Right, semicolons or not using semicolons aren't going to break your code all the time, but every once in awhile it might cause a problem so we use a linter to help prevent that from happening. Now, JSLint was the first linting tool that came about and it was created by Doug Crockford back in 2002. It came preconfigured, it just worked right out of the box, using the set of rules that Doug Crockford wanted in his code and ultimately it still kind of sits that way. It's not very configurable. If you like the rules the way he likes them, then it works great, but I prefer something a little bit more configurable so there's a couple more options. The one I prefer is JSHint and JSHint is a fork of JSLint. So it started off of JSLint and they took a fork of that. It's much more configurable. There's a config file involved and we can change all kinds of stuff. It's got built-in package support. So if you're using a package code like jQuery, then it comes preconfigured for some of that. It's not very extensible, which means you can't extend on it very well and for most people that's just fine, but for some people it's going to be more of a problem. So there's one more that I'm going to just let you know exists and that's ESLint. ESLint's the most recent of the three and it includes some custom rules support just like JSHint does, but it also has lots of configuration options. It's actually much more configurable than JSHint is and with that comes some configuration struggles and for someone new using it right out of the box, it can be maybe a little bit of overkill, that doesn't mean it's not good, it's great, but if you just want to use something to get started, JSHint might be the way to go and so what we're actually going to do now is we're going to work through getting JSHint up and running on your machine. So JSHint is the one I'm going to recommend just for right out of the box just to get stuff done quickly. Now getting started with JSHint is really easy and there's a couple of different ways we can do this. The first one's in the browser, which may seem kind of weird, but I'm going to show it to you just in case you're interested. The way that works, go to JSHint.com and you can just paste your code right in here. And if I take the semicolon off of there, we get a warning that says "Hey, you're missing a semicolon" and if we do the same thing here, this is semicolons is all we've talked about so that's all I'm going to show you right now. But there you go. Also it'll tell you cyclomatic complexity and we may talk about that later and all of these things that are wrong with your code. You might imagine copying and pasting your code into JSHint.com is not the most efficient way to do this. So there's a couple other options. The next one is using brackets and we kind of looked at this earlier when we said we had a plugin to brackets that right here tells me, "Hey look, JSHint, I'm missing some semicolons everywhere." So we come in, semicolon, semicolon, semicolon, we can save that. I'm getting one error left, we haven't talked about that one yet so we'll come back to that. The way that I'm doing this inside brackets is I'm using a plugin. So if you can click the little Lego looking thing, then I have something called JSHint that I've installed into my brackets. So if you just click the Lego, go up here to Search and type JSHint, you'll find it right here. Then you can just install it that way. Now, this is actually very convenient because as I'm writing code, it'll warn me, hey you've got problems, something's going on. It is not necessarily the most convenient for a holistic project. Oftentimes you'll want to run a linter, or JSHint, across your entire code base and the way you do that is with a command line. So if I come to a command line and I do an npm install -g, I can run JSHint. Once I've got that installed, since I ran it with the -g, I can just type JSHInt right here at the command line and I can do JSHint and I've got one file in here, this one in my brackets window, semi.js, run that and I get no errors and I get no errors because I took the semicolons. Let me take the semicolons out and I'll run this again and now you see I've got some errors going. So those are the three ways that you can run JSHint. Now for the command line, you can also plug it into your gulp or your grunt or your npm scripts or however your particular situation is that you're running your build utilities or whatever you want to do there. I for one, whenever I have a gulp script running, I've got JSHint that runs inside of that. Alright so that's JSHint, that's up and running, and so now as we go through the rest of these syntactical things that we've got going on we'll refer back to JSHint and let JSHint identify those for us. But instead of just saying hey run JSHint and you'll see what's going on, I want to actually show you the issues that arise when you do some of the things that we're going to talk about. Curly Braces One other thing I want to talk about really quick before we move too much further is the curly braces and we touched on this a little bit when we were talking about semicolons, but I just want to call it out real quick to be explicit on what I'm talking about. So if you look at this code, if you're a .NET developer, then this probably looks exactly right. This is the way we do curly braces in .NET. It's just the way it always is. JavaScript, however, we don't do it this way and the reason for that, if you can look at this, if you've been paying attention, you should immediately be able to tell me what's wrong with this. Right here, automatic semicolon insertion is going to stick a semicolon at the end of that return statement, which means that this whole thing breaks. So what you have to do, the only way around that, is to stick a curly brace right there. Now, everything looks funky because I've got some curly braces on the next line, some curly braces on the same line, and it just doesn't work. So the recommendation is we put curly braces on the same line and that is only for consistency's sake because there are some cases when it is required, we must do it. So in that case, since sometimes we must, that means we always should and so curly braces pop up to the next line. Equality Let's take a minute to talk about equality and the comparison of things in JavaScript. Now one question I see quite a bit is how do I compare two things? I got double equals, I got triple equals, what's the difference, when do I do what, so on and so forth. How do I compare things in JavaScript? So what I want to do for just a little bit is look at some simple little examples that will walk through what the equal signs mean when we're dealing with objects and types in JavaScript. So here we've got something very simple, X equals one, Y equals one, if X equals Y. Now when I run this, what do you think it's going to be? Am I going to get equals or not equals? Now if you already know the answer, that should be obvious, if you aren't sure, you can probably guess based upon the fact that I'm even talking about this, we're going to get equals, which is weird and that's not at all what we expect because one does not equal the string one and what this comes down to is this double equals. That double equals checks to see if those two are the same thing. So the double equals says hey if variables are two different types, it's going to convert them to be the same type. So that means in our example I've got an int and a string and those are both primitive types and it says hey those aren't the same thing, so let's convert them, one, one. There I get X == Y so hey this one is an int, this is a string so I'm going to convert that and be the same thing. Now, that's great in some cases, but hey what about this? If one equals true, well they equal the same thing because I'm going to convert this one to a Boolean. Or if zero equals false. Well, number, Boolean, if I convert the number zero to a Boolean, what do I get, I get false. There you go. So == does a conversion to the same type. Now in order to get around that, we have the triple equals operator and what the triple equals operator is just says hey we're not going to do a type conversion. Triple equals means I'm not going to do a type conversion. So first thing it's going to check is are you of the same type and if you are, great, if you're not, false. So let's check that out. So if I say hey X equals zero, Y equals false and I switch this to a triple equals and I run this, now I get a not equals because zero does not equal false. Those are two very different things. Same thing if I do a one and I do a string one, those two things are not equal to each other. So generally, we want to use triple equals because we want to make sure that we're not doing behind the scenes type conversion when we're checking to see if two things are equal. Now one other thing I want to talk about when we're talking about equality is this. Boom, if(x). And we oftentimes do this to say hey does this exist? Does X exist? And that's great because in this case hey check this out, X exists. If I change this to var X, X does not exist. That seems to work just great except that based upon what we've learned up till now, this is basically the same thing as saying if(x == true). Well guess what, if x == true, what it's going to do is it's going to say hey true is Boolean, I need to convert X to Boolean. It's actually going to try and convert this to Boolean. So if X == 0, not ==, if X = 0, well zero is false. It went converted to Boolean. So hey check that out, it doesn't exist even though I know it exists. So that's not the right way to go about checking to see if something exists. Actually it can get even worse if I remove X completely and I just say if(x). In this case, remember what I just said, it's the same thing as saying == true, well it's going to do a conversion on X and it's going to try and convert something that doesn't exist at all and what you're actually going to get, this is one of the rare instances where we actually blow up. You just an X is not defined, which is not good. A lot of times JavaScript fails silently and that bears its own problems and we'll talk about that over in module three, but in this case JavaScript's going to blow up because this X doesn't exist and actually what we're trying to check is if X exists. So that's not the right way to go about this at all. So what we're going to do is we're actually going to check to see if the type of X is defined or not. So real quick, let me show you what that means. So if I have this and I do a console.log on typeof X, check this out. Hey, X is a number. If I change it to a string and I run it again, hey it's a string. Now if I get rid of X altogether, actually let's do this first, if I just don't assign it anything, hey X is undefined. But also if I get rid of X altogether, I still get undefined. So what we can do to check to see if X exists is to check to see if typeof X, if typeofX does not equal undefined, then I'm not doing that conversion and so now I can run this safely. Hey, it doesn't exist and now it exists. So this typeof X does not equal undefined is the safe way for us to do what a lot of people would just do with that. So hopefully that makes sense and that works out for you. To sum that whole thing up, we're going to say the best practices use triple equals as the default. Nine times out of 10 you want to be using triple equals to make sure that you're not doing behind the scenes type conversions, especially where you've got zero when really you don't want it to be false. And on top of that, when we're just checking to see if a variable exists, use typeof and undefined instead of just saying if(x) because that will blow up every once in awhile. Alright, that's equality for JavaScript. Configuring JSHint Now one thing to call out real quick, notice I've got the double equals and I told you we don't do double equals, we want to do triple equals instead. Well if you look down at my JSHint down at the bottom, I've got two console is not defined errors, which is fine, but I want my JSHint to tell me about my triple equals issue and because I want to handle this stuff with my JSHint with my syntax and JSHint has a series of options available to enforce rules that are not enforced out of the box. So this is that configuration piece that we talked about earlier when we were talking about JSHint. And you can do bitwise, you can do camelcase stuff. If we go all the way down, there's one called eqeqeq that's going to prohibit the use of double equals in favor of triple equals. This is what we want to do and this is what I want to use and the way we do that is I'm going to right-click and I'm going to create a new file called .jshintrc and all we're going to put in here is a JSON object and this is a JSON object that basically has a set of parameters, in this case eqeqeq and true. Now that I've set that and I hit Save, I'm going to go back over to my equals and all of the sudden down here at the bottom, hey I expect triple equals and instead I saw double equals. Right here, I switch that to triple equals, I hit Save, now that error's gone. So I can go over to my JSHint options, look through what these enforcement options are, there's enforcing options, and I can configure JSHint to report on errors that I want to use in my code. Variables The next thing I want to talk about for a little bit that's just different in JavaScript than it is in other languages is variables and the way variables are used and the way they're defined and all these things and if you're not quite sure why we would take some time to talk about variables in a best practices course, let me show you something real quick that just is weird. Now if you remember from a couple of clips ago, we talked about the concept of variables not yet being defined and how that throws errors. Well right here I've got one line of code, console.log(myVariable), and that should, as we all know, as we saw just a little bit ago, throw an error. If I run this code, I get an error just like we would expect. My variable is not defined. So if I do this right here and I just define my variable, you would expect that to still error out because I have defined my variable after. But it doesn't. Now it just gets undefined and that's a little weird. But let's make this a little more weird. I'm going to assign my variable a value and now I'm going to run it. I just got undefined again. But I've assigned my variable a value and we know that this line of code was read because I'm not erroring out. Remember, if I comment that out and I run it, now everything blows up. So variables work a little bit different in JavaScript and I want to take a couple minutes and kind of talk about what that looks like and why it's weird and then we can dig into what some best practices are around variables in JavaScript. Now this behavior is often called hoisting and hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope and you may have heard that before and that's not really quite what's happening here and so I want to take just a minute and let's talk about what actually occurs when a scope is created in JavaScript. Now according to the Standards, "A var statement," so when we're declaring a variable, "a var statement declares a variable that are scoped "to the running execution context's VariableEnvironment." So usually that's a function. "Var variables are created when they're containing "Lexical Environment is instantiated "and are initialized to undefined when created." So that's a lot of words, there's a lot stuff there, but let's break this down into two pieces. The first one being variables are created when they're containing Lexical Environment is instantiated. So this is where the hoisting things come from, right, it's the variable declarations are moved to the top and they're not really moved to the top, and we'll walk through this here in just a second, but just know variables are created when their containing environment is created. And secondly they are initialized to undefined when created. So this is what the Standards say, this is how it's supposed to work. So let's look at this for just a second. Let's go back and look at our two lines of code here. So I've got two lines of code and I've got my list of variables associated with this code. Okay so as JavaScript, as the JavaScript compiler enters this scope, it's going to start up at the top and just say hey okay, I'm creating a new scope. Then it's going to look down through the two lines of code that exist. So first it's going to look at console.log, no variable declarations there, then it's going to look at the var myVariable, there's a variable declaration there. So it's going to go ahead and create that variable, myVariable, and it's going to set it to undefined. Then once that's done, it's going to go back to the beginning and now it's actually going to execute the code and so it's going to go to console.log(myVariable), then you're going to get undefined, remember that's what we were getting before. Then it's going to hit this line, var myVariable = 10, well it's got a variable 'cause we've already done that part and it's going to set it to 10. So that's what hoisting's all about and I understand why we look at it the way we do of moving those variable declarations up to the top. The danger in thinking about it that way is that we're tempted to take that whole line and move it to the top and that's not at all what happens. The only piece that gets moved to the top is just the var and it doesn't really get moved to the top, it's just the whole scope is scanned, picks out all the variables, assigns those variables to undefined, and then goes through and executes your code after that. Let's throw one more wrinkle into this whole thing so that we can get a little bit more of a taste of why this might start to cause a problem. Now we've got the same code we had before except I've introduced this function, function func, with my variable. Now when I run this code, what's going to print out? Think about it for just a second. Don't try it, just see if you can tell. We'll run this code. If you said 10, you are correct because the function isn't ever used. So let's actually run the function. All func does is assign 25 to my variable, that's all it does. Now I get 25 and the reason for this is the way this variable hoisting slash scoping thing works and if we come back in here and look, because there's function scope, function level scope, it does a scan through and says hey there's no variable declarations, that's cool. So then it moves on and now it's going to go through and it's going to execute. It sees the line, line four, myVariable = 25. It's going to go to the runtime and say hey do I have a variable called myVariable in my function scope? And it does not. But then it's going to break outside of that and say hey do I have a variable up a level in the next scope? And it does, var myVariable = 10, that happened earlier before. So it's then going to assign 25 to myVariable and we print it out. So that's what happens. Now, check this out. Based on everything we've talked about up till now, what happens when I do this? What is console.log(myVariable) going to print out when I run that? You've got three options, it's going to print out 10, it's going to print out 25, or it's going to print out undefined. All three are probably equally viable, but I'm hoping after the course of this conversation, everything we just described, you're going to say 10 and you would be correct and the reason why that happens, to move this conversation back over to slides, is because of the way that hoisting works. We're going to run through the current scope. So at the end of this scope, we're going to run through, it's going to hit the var myVariable = 10 and then it'll run through everything, no other variables are defined so that's great. Then when func is executed, then it's going to create the variables inside the function scope. So we'll start up when we declare the function, we're going to scan through once. So myVariable = 25, so not a declaration, it goes to var myVariable, so that's a declaration so now we've got a myVariable = undefined in our func scope. Then we're going to execute our function after that, myVariable = 25. So hey, do we have a myVariable in our function scope? Yes we do, myVariable = undefined become myVariable= 25. So we're done executing our function, now we do our console.log. Well in our global scope, we have a myVariable and that's equal to 10. So that's what gets executed. So the key difference there is that the scope is fluid and it's fluid in most languages when you're talking about function scope to global scope and all those things, but what happens a lot of times is we write large JavaScript. We end up declaring variables down inside close to where we're using them, because that's how we do it in other places, instead of putting all of our vars up at the top of our function scope and so best practice here is all of your var declarations go to the top of your scope just because you want to avoid potential confusion and potential conflicts knowing that it happens. So if I've got a function, all my vars go to the top. If I've got my global scope, all my vars go to the top. Now that doesn't mean you have to initialize everything up at the top. You just if you're declaring a new variable, stick it up there at the top of your function or at the top of your global scope so that you know and it's very clear where your variables lie. Now in most cases, if you're doing clean code, you're not going to have the same variable name spread out all over the place. That's its own bad practice, right. Don't have myVariable as your variable name at all, but on the other hand if you are, only have it for one variable, don't have it for two and that avoids more confusion. Now, this whole concept of hoisting causes even more problems when we get over to talking about creating functions. Functions Alright, the last thing we're going to talk about for syntax and just the syntax of JavaScript is functions and how functions work in JavaScript because there's a little bit of a difference when it comes to JavaScript and the way functions work and mostly that comes from the fact that functions in JavaScript are first class objects. They are just the same thing as an int or a string or a Boolean or an object, a function is a function, it's a type, it's something that can be and so because of that there's some weird idiosyncrasies that go on around functions that we want to identify just so we know how to handle. Alright, first and foremost, when it comes to functions there's two types of functions or there's two ways to create a function. There's a function declaration and a function expression and what we want to do is let's spend a little bit of time, we'll just write a little bit of code real quick to show the difference between declarations and expressions and if you've been following along up till now, if you didn't just jump in here, then this should become very evident to you what the issues are going to be when it comes to using expressions over declarations. Alright so I've got a function, function myFunction and it's got a printout console.log. Let's just execute this function right here. So if I execute that and now we run this, we're going to get our hi from my function. That's completely expected. Where I execute this function from is completely irrelevant and the reason for that, if you remember back to our conversation on hoisting, the compiler's going to run through our code twice and the first time it runs through the code it's looking for variable declarations and it also is going to pull out function declarations and so when the compiler runs through this the first time, it's going to see this function myFunc right here and it's just going to take that whole thing and it's going to say hey I know about this function called myFunc and so when it starts to run through the code the second time to actually execute it, it's going to execute the function and it's going to be fine. This is how functions work everywhere. If you're a .NET developer, Java developer, any of that stuff, this should be obvious and you're probably wondering why we're talking about it, which is cool and I get it, but here's the thing. In JavaScript, functions are first class objects, which means I can assign them to variables and that's called a function expression. So I can actually do this. I can say var expression equals a function and when I do it this way, let's just copy this, and I run this function expression and I execute that, let's see what happens. I'm going to get my hi from myFunc and I get hi from my expression. That's cool, everything works. If I move this up here like that, what do you think's going to happen? Think about everything we've talked about up till now and in your own mind think about what's going to happen when I execute expression and if you say you're going to get undefined as not a function, you are correct and the reason why you're going to get that is because of hoisting and the conversation we've had up till now. So hold on, let me just prove my point. Boom, expression is not a function because expression is not yet assigned as a function. So hold on, let's look at this. When the compiler runs through this the first time, it's going to come to line five and it's going to say var expression =. Well I've got a variable and if you remember how hoisting works, it's going to say yep, I've got a variable called expression and it is undefined. Then it's going to go to the function myFunc and it's going to set that up as a function. Then when it executes the code, expression at this moment is undefined and then it's going to go down to line five and it's going to assign a function to expression and then after that line we can use expression as a function. Now the question is why, why do we care and why would you ever do this? And the reality is if you're passing functions around, and sometimes you will, this is how this works because when we do callbacks you can assign callbacks, when you're assigning alerts or things like that, if you're doing some behavioral design patterns where you're doing messaging, you might do something like this where var expression = and something, that's a function. But don't lean on the function expression side because this will cause problems every once in awhile where you're defining your functions and then you go and you try and use them and they're not actually a function yet. So when it comes to functions and the two types of functions that you can do, let's talk about best practice about the best way to do your function. When it comes to best practices, this is really what we want to do. So any time you're creating a new scope, your variables go first, declare your variables and do this as a matter of habit so that you never get into a situation where 3/4 of the way down a page, you need a variable and you just declare your variable right there because you don't know what impact that's going to have up above it because of the way hoisting works. The very next thing you do after your variables is to create your functions and when you do it this way then you don't have to worry about hoisting or similar things to the way variables work, right. Everything goes up at the top. Down at the bottom, your run code goes after your variables and after your function declarations. Now when you create a function, you create a new scope. So the same process applies. You do your variables first, then you do your functions, then you do your run code down at the bottom. So every time you're creating a new scope, which is a new function or your new global scope, that same pattern should apply. You've got your variables first, then your functions, and then you've got your code to run everything down below. Summary So that's it for module two for our conversation about syntax in JavaScript and the way syntax works and how it's a little bit different in JavaScript than it is in some other languages. We started off with a talk about semicolons and the end result of that conversation was I don't care. There's a lot of conflict and a lot of conversation on semicolons out on the Internet and once you've walked through how semicolon insertion works it just doesn't matter and so my best practice for that was I use them and I use a linter that will tell me when I've missed them so that the .01% of the time that semicolons might cause me a problem, it'll solve it. So we started with probably the most talked about thing, but completely the least important thing that there is when it comes to JavaScript. We talked about linting and how using a linter's going to help us with our syntax to help make sure that we're following the practices that we want to follow because we can configure those and make sure that we're doing the same thing over and over every time. We talked about equality, double equals versus triple equals, best practice there being use your triple equals. Triple equals is a better sense of whether or not something is the same than double equals because double equals does a type conversion first and that might cause some problems. We talked about variables and most importantly around variables we talked about hoisting and what hoisting really is and how we get around some potential issues with hoisting by making sure we're declaring our variables up at the top, always up at the top. And the last thing we talked about is functions and for the most part there's two types of functions and there's declarations and there's expressions and depending on who you talk to, it's better to use expressions or it's better to use declarations and really it's going to come down to if you always declare your functions up at the top, right underneath your variables you've got your functions, then you're not really going to run into too many problems no matter what you decide to do. But when I say that, the most important thing is consistency is key when it comes to syntax and actually when it comes to everything. All through this course you'll hear this same mantra, consistency is the most important thing. If you use semicolons sometimes, just use them all the time, triple equals all the time, if you use function expressions use them all the time, if you use function declarations instead, consistency, continuously do the same thing over and over again so that you don't run into issues where sometimes it works, sometimes it doesn't. You get yourself in a habit of always doing the same thing. Behaviors Introduction So, in this module we're going to talk about some JavaScript behaviors. And this is going to tie into the conversation we were just having about syntax. But I'm going to expand that conversation a little bit and talk about some of the things that JavaScript does that you may not know that it does. And it may be a little weird. So, we're going to talk about, like I said, things that JavaScript does that you don't necessarily expect. And when we're talking about semicolons, and semicolon insertion, this RSpec actually says, as a matter of convenience, JavaScript's going to stick semicolons in there for you. It's going to do it because it's trying to be helpful. It's trying to be nice. Well, there's a lot of things JavaScript does to be helpful. Either to protect you from errors or to, you know, just make things, maybe, better. And that's not always a good thing. Because sometimes JavaScript is doing something that you don't want it to do. Or you don't know that it's doing and you think you're actually doing something you're not. And so, in this module I'm going to walk you through some of those things, I'm going to walk you through some of these weird behaviors that JavaScript has that you may not even know are happening. Probably not, there's a lot of these that a lot of people think they're doing that they're not actually doiing, because JavaScript is protecting them. So, in this module we're going to kind of dig into what those look like, and we'll talk about strict mode. And how to prevent JavaScript from doing some of these things that you don't want it to do. Global Variables So, I want to start out this conversation of behaviors in JavaScript with a second half to our conversation about variables. Now, we talked about variables and how variables are referenced when they're compiled and all of that. But I want to walk through a slightly different version of this conversation to get us to get us going on this conversation about JavaScript behaviors. So this a very simple little program. It has a function that's going to print a string that's sent to it, and basically, it copies whatever's passed into it to a variable. And then it prints it out. Really simple, really straightforward. We're creating a variable as toPrint. Just, we're going to use that to play around with a couple of things, and basically, the only thing this whole application's going to do is print out the word hello when I run it. So if I run this, there we go. So this works exactly the way as we would expect it. Now let me add another console.log here. And let's add toPrint. Now, toPrint is outside of this function. And if we go back to what we talked about before, so, we've got function scope, so when it gets to this toPrint reference it's going to say, "Hey, do I have toPrint in my function scope?" And I don't. So then it's going to look outside of the function scope. And it's going to hit this variable for toPrint. So, let's run that. There you go, now you've got Hello and Print Me both printed out. So we know that it works in that direction. But what we also know is that we have function scope. So, this var is not accessible outside of this function. So, if I do a console log and just do stringToPrint right here, we'll take this line off just to avoid confusion, what's going to happen? If you watched module two you should know that this should blow up. I should just get a big fat blowup and nothing will print. And there we go, everything blew up. Because stringToPrint is not defined. We don't know what that is. So, we have a nice function scope that works exactly the way that we would expect. Right up until I'm coding along and I forget to do my var. Now, if I take that var off, so, same thing. This stringToPrint is not defined. And here it's not defined. So what do you think's going to happen? I should blow up, right? Well, if I run this, it's actually going to blow up. And it's going to blow up because it still doesn't know what stringtoPrint is, but if I move this underneath and I run through the print function once, now check this out, now I get Hello twice. that is not what we would have expected to happen. And the reason for that comes from the way the variables are declared. Remember, we go back to, we scan down. At every var we create a reference to that variable and on and on and on. Well, what happens here is when this print happens, it runs through this function and it gets to line four. And on line four it says stringToPrint = out. So, the runtime goes up to the scope and it says, "Hey, I need a reference to stringToPrint." And it doesn't have it. Now, there's two types of references. Let's be clear here, real quick. 'Cause there's two types of references. There's this reference, which is the out, which would be the same type of references we have here. The equals out is the same type of reference as when we're doing the console.log stringToPrint. That's an RHS reference. And RHS just means right hand side. It's not fancy, that's just what it means. And that means, hey, give me the value of this variable. Well, that variable doesn't exist. So obviously it doesn't have a value. So obviously something's horribly wrong. So it throws an error. In this case, we have an LHS reference. Which basically means a left hand side reference. On the left hand side of the equal sign. Well, remember how in the semicolon insertion module we were talking about, you know, for convenience JavaScript is going to inset semicolons for you. Well, JavaScript tends to do a lot of this 'for convenience' stuff. And so what happens is we get a left handed reference to stringToPrint and it goes up to the global scope and says, "Hey, I have an LHS reference for stringToPrint. Do you have it?" And the global scope will say, "I do not have one. "But you probably intended to make one and you just forgot. So, guess what, I'm going to make it for you." So, because you're trying to store something in this variable, stringToPrint, the global scope says, "Hey, yeah, I'll do that for ya." And that then starts leaking things up to the global scope. So now, because this print function was executed, and because out was assigned to stringToPrint, stringToPrint now has a value and stringToPrint is now in the global scope. So, my console.log here actually has a reference to stringToPrint. So basically, what that means, just to sum that quick little conversation up, if you forget to put a var in front of a variable when you're declaring it, that variable gets leaked all the way up to global scope. Which is probably not what you intended to do. And so this has the potential to cause problems where you did not expect them to happen. Not all the time, or this would be obvious and everybody would know it, but sometimes. And so, these things tend to happens, actually, more often than you'd think. Not necessarily here, but when we start talking about this later, that happens a lot. So what we're going to do is, let's talk about how to fix this problem. And how to fix this JavaScript helping me where I don't want it to help me, just because it thinks I missed something. Strict Mode So the way we're going to deal with situations like this is to use something called strict mode. And you may have heard of strict mode. And you may have been told to make sure you do everything in strict mode. But not really had that explained to you why that is or what is does for you. So, what I want to do is spend a couple of minutes and talk about what strict mode's going to do. And basically, it all boils down to this. JavaScript's trying help, don't let it. JavaScript's going to try and help by, in this case, it knows you want to assign a variable, so let's create a variable for ya. JavaScript's going to do some things for you. Don't let it do it, you know what you want to do, you do it. So the way we deal with strict mode is to create a phrase at the top of our file called 'use strict'. Now, when I put that up there, what worked just a second ago will now blow up. Now it blows up when I run it, because I get that stringToPrint is not defined. And notice where it's at. So, we're back up at the assignment. So now I'm blowing up where stringToPrint equals out. And it's saying, "Hey, stringToPrint's not defined." Before we did 'use strict' it would create this variable for us, because it assumed we wanted it. Once we start using 'use strict', now it's going to blow up. And depending on how you're working, that may or may not be what you want. But I would rather, hey, let's actually have an error so I know something's wrong. Instead of covering up the error and pretending it didn't happen. Which is what non-strict mode code is going to do in this situation. Real quick, let's talk about scoping. You may not want 'use strict' to be in the global scope of your application. Especially if you're in the browser. Because it's going to apply that strict mode to everything. And you don't necessarily want to do that. So we're going to take that and we're going to stick it inside our function. Now, if I stick it inside our function, and let me get rid of this, now this is going to error out still. So I run this and I still blow up. But if I put my var here, everything's going to work. I can prove that strict mode is contained just to this function by coming down here and saying a random variable equals 23. Now, when I run this with 'use strict' inside my function everything works. Which, you know, at first, even when I hit that I'm like, "Wait a second, that's wrong, because it should blow up." Well, and it should blow up, but it didn't blow up because 'use strict' is stuck inside the function. And so 'use strict' scopes appropriately. If you're doing Angular code or something and you want to do 'use strict', wrap everything up in an IIFE. Stick 'use strict' inside your function, and we'll show you that later, and then we'll see how that goes. Now if I move this 'use strict' back outside and put that up here, now it's going to blow up. And it blows up because randomVariable doesn't exist. So, what we're going to do over the course of this module is we're going to look at some of these weird things that JavaScript does, where they try and help you when you probably don't want it to help you. You want to know what's going on so that you can eliminate these weird, random things that tend to happen from time to time. And I think a lot of times our confusion around JavaScript, or the reason why JavaScript is sometimes hard for us, is because it does things that we don't anticipate. And every once in awhile we think, "That shouldn't do that," and it does it anyway, because it's trying to help us. And so, let's talk through what this 'use strict' does. And some of the behaviors that JavaScript has. And the best practices around how to deal with that. And a lot of those best practices are going to be, well, don't do that, and use 'use strict' just to prevent you from doing it. Read Only Properties So, let's for a minute about read only properties. Now, if you're creating an API or you're creating an object of some sort that you want to protect, it makes sense to create that object or the properties on that object as read only. So that you know nobody's going to come along afterwards and reassign them. 'Cause somethin' different in JavaScript, is if I don't like a function, I can change it to somethin' else. And that can cause problems sometimes. So, let's look at some code. I've got an object, just called obj. So, I've got an object, var object. And it's just an empty object. Then I'm going to define a property called readOnly on this object, and what defineProperty lets me do is I can set it up as either enumerable, whether when I loop over an object I can see this value, and I'm going to shut all that stuff off. But the important one I want to see here, I'm setting writable to false. And that means that the value that I'm giving it, 'This variable is read only', can't be written to. It's stuck that way and you can't ever change it. So, like a constant, you know, that's the way it works. And then on line 10 I'm going to print this out. And this is going to be exactly what you'd expect. I'm going to run this, and there you go, this var is read only. Very straightforward, no surprises. Right up until I do this. I'm going to now say obj.readOnly = 'I wrote this'. Now, when I run this code, think about this for just a second, what do you expect to happen? You would one of three things. Either I'm going to assign it and my writable doesn't work, or I'm going to blow up, actually, one of two things. Those are the two things I would expect to happen. And really, I would expect an error here. Because I'm doing something that's clearly not allowed. But when I run this I get the same answer, nothing happened. So, I'm clearly intending to write something. Because maybe I didn't know that it wasn't writable. But that value just disappears. And this another instance of JavaScript trying to be helpful. You're trying to write something and, obviously, you know, you didn't mean to, because this is not writable. So, there you go. I'm just going to ignore it and we'll move on with life. I don't want that to happen. If I'm doing something wrong, I want to know about it. And in this situation especially, if I had an example of complete and completed on a function and I'm setting, complete is a function and completed is a true or false value, well, if I'm accidentally setting the function equal to true or false instead of setting complete or completed to true or false, well, you know, I'd kind of want to know if that was broken. So this is another instance where I'm going to do 'use strict'. And now when I run it, it's going to blow up. And it's going to actually give me the error that I would expect to get: Cannot assign to read only property of readOnly. I would have expected that to have been the case anyway. And 'use strict', in this case, is going to actually give me the error that I would expect to have on my readOnly. So, the best practice, 'cause as we're talking best practices, be aware that, one, you can set things to not writable. And if you're building out an object to use, that might be a good idea. To set your properties, especially your functions, as not writable to prevent other people from accidentally overwriting things that you don't want them to overwrite. On top of that, use strict mode so that, you know, people actually get an error instead of just not knowing that nothing happened. Deleting Properties Another weird example of what we're talking about here is when we try to delete something. And some weirdness happens that I want to look at. So, I've got an object, var object a is 100, b is 200. When I run this console.log I'm going to print out exactly what I want. Now, when I'm done with, let's say I'm done with a. And I want to clean up after myself, which is the right thing to do. JavaScript's givin' us this cool keyword called delete. And I can delete obj.a, and now when I run this a is gone and I only have b. And that's the proper behavior. That's exactly what you'd expect. The problem comes when we start to think that delete does more than it actually does. So, for the purposes of this, let's create another variable called, let's call it myVar and we'll make that equal to the 10 so it's somethin' different. Then down here I'm going to print out myVar. Now, when I run this it's going to do exactly what you expect. I've got my b and I've got my 10. Now let's say I'm done with my var. Well, let's just delete that. Now it should actually, maybe, throw an error. 'Cause, back to what we've been talkin' about all along, I've got an RHS reference to myVar, 'cause I'm trying to pull the value of myVar and it doesn't exist, so I should get an error. Well, actually, what's going to happen is nothing. It's going to work exactly the way it would be expected to work. And actually, same thing here. If I just delete object, let's just get rid of the whole thing, same thing, doesn't happen. So this is another one of those situations where JavaScript, in order to be helpful, in order to not crash, in order to say, "Hey, I'm going to keep runnin' here even though you did somethin' that was a little weird," well, that might be, but that's not the behavior we want. If I delete something, I want it to be deleted. I want it to go away. So we come back to the 'use strict' keyword. And now when I run this, we actually get what we're expecting. When I delete something that I can't delete, it blows up. And it says, "Hey, we're going to throw an error." Which is more in line with what I would expect if I'm trying to delete something we couldn't delete. So, delete keyword. Delete is only good to remove something from an object. You cannot delete variables or objects, it doesn't work. If you're not running in strict mode, you think it might work, but it really doesn't do anything. And so, again, that's another situation where the 'use strict' keyword is going to help us understand what's actually going on, instead of just pretending like nothing happened. Duplicates All right, one more weird thing that happens is dupes. So, look at this code, what's it going to print out? We've got three options. You've got one, three or an error. And you probably, by this point, will assume no error. So, it's going to be one of the three, Well, let's run this, and we get three. Which is hopefully, by this point, what you would expect. That's weird, and it's kind of dumb. And it's maybe a little contrived that I've got this. 'Cause you would never do this, right? I mean, this is obvious. But I have seen functions that have fairly lengthy parameter names. Like if you're passing in a user and you're passing in all the properties of the user as individual arguments, well, I've seen that happen. And you want to make sure that you're actually, you know, getting an error, again, the way you are expecting it to. So, one more time, I'll use strict. Now we actually get an error. That's it for the hey, I don't get an error when I expected to stuff. But there's a couple more weird things that JavaScript does that I want to point out before we move off to something else. Octals and Hexidecimals, Oh My All right, so take a look at this. What am I going to print out to the console? If you said 132, then that is a fantastic guess, but you haven't been paying attention at all to anything I've been saying, because that's 130. And that's weird, and that's not what we expect. Because I want to keep things pretty and line them up nicely. And everybody likes nicely lined up code. So, you know, 002. Let's keep everything clean and neat and organized. And so, this is going to be our 132. No, it's not, because I didn't add the z. Now it's going to be our 132. Okay, here's what's happening. If you stick a zero in front of a number in JavaScript, JavaScript's trying to be helpful, says, "Hey, that right there is an octal number." Which is kind of a weird way to define an octal number. So, that's how it works. So 012 in octal is 10. So, 120 plus 10 is 130. And that's exactly what we would expect if we knew that we were dealing with octal. But we don't, so just for reference, if I want to do hexadecimal, I do x. Now I'm going to get 140 that I would expect from hexadecimal, because 12 in hexadecimal is actually 18, right. Okay, so let's fix this. I want to be able to line up my numbers appropriately and say hey, we can't do zero, zero. And actually, there we go. Remember, I can't do that. So, in this case, 'use strict' is just preventing us from doing something that we didn't even necessarily realize we were doing. Zero doesn't work. If I want to use octal, then I have to actually convert it using parsing. So if I really want to use octal, like I really want this 12 to be octal, I'm going to do this instead, I'm just going to do a parseInt. And then this second parameter to my parseInt actually gives me the ability to set it to octal. So, we're just eliminating that shortcut zero thing. So, if I expect that to be eight, let's get rid of the z here just to avoid confusion. 120 plus this now equals 130. So, 12 in octal is really only 10 in decimal. So, I can still do octal with 'use strict'. But this is going to cause an error, because it's going to behave differently than how I would expect it to. With All right, two more things to talk about in this module, talking about behaviors and kind of how things work in JavaScript. And this one, we're going to talk about the 'with' statement. And if you're coming from C#, with happens. And with is supported in JavaScript. And let's look at what that looks like. So, here I've got an object. An object has a object called a. a has an object called b. b has a string called c. And c is just 'hello'. So when I'm interacting with this object, if I do my console.log here, I've got object.a.b.c and I'm going to print out 'hello'. Now, this is painful. And how many of you have ever worked with objects that tend to grow, and now you've got sub-objects and sub-objects and now you're dealing with things that look crazy like this. So, JavaScript has a with statement that can simplify this. So, with, let's just say, object a and b. I can do the c. Now, doing that, now it all works. And this looks cleaner, and this is awesome. Except, it's got some problems. And the first problem being what happens if I do this. Because of the way scoping works in JavaScript, and it's, remember, a little different than in some other languages, I have now clobbered c. This variable right here goes away inside the block that is lines 11 through 13. That's painful. And that's not exactly the way or the behavior we would like to have. As a matter of fact, really, this has become such an issue that just by looking at your code, you don't know what c refers to. That with has actually been deprecated inside JavaScript. It still works, obviously I'm still doin' it. But its been deprecated, and it's been said to stop using it. And as a matter of fact, Brendan Eich talked about this on Twitter several years ago and he said this: with violates the lexical scope, making program analysis for security hard to infeasible. And basically what that means is when I look at this, I don't know what c is. Because, now, obviously when you look at this code, see, we can figure it out pretty quickly. But none of work in an environment that looks like this, right? Most of our code becomes very large. I mean, if you're dealing with Angular, Angular is 20,000 lines of code, right. So, the idea that when you're inside a with block you don't always know what that variable refers to, causes problems, and so, Brendan Eich has said not to do this. And to the point that when we go back to using strict, this actually will blow up and say, "Hey, strict mode code cannot use the with statement." So, we had a problem and we used with in order to solve that problem. And that, now I told you you can't use with. I got you all excited about how to solve this cool little thing with a with statement. And then I took it away from you, and that was mean of me. But there's a different way to achieve this same goal. And that's with an IIFE. And so, I can wrap, we talked about IIFEs quickly when we were talking about semicolon insertion, because if because if I don't have this semicolon here, this is going to cause me a problem. But if I do this, and I pass in newVar and I pass in obj.a.b, now I can do all my work right here. I can do my CL, my newVar. That's going to print out my hello just like I would expect it to. There we go, that's what I wanted. All right, so then, this way I can simplify just like I wanted to, but now I'm safe. And I'm doing something the right way, and protecting my scope. And I'm explicitly calling out the variable that I'm going to be using inside my function, instead of having it be not as clear as it was in my with statement. So that's why with went away. It's not an optimization thing, it's nothing like that. It's strictly because when you look at your code you want to know exactly what's happening. And in this case, this is a little easier to follow than in the instance where I had with goin' on. And a lot of that has to do with the fact that I can define what that variable's going to be, instead of just having to take whatever object.a.b gave me. So that I know I'm not going to accidentally step on top of something else. What Is This Anyway? Now, we can't end a conversation about behaviors in JavaScript without talking about the this keyword. This is probably one of the most confusing and irritating things that are involved in JavaScript, is figuring out what this means, what this does, all of those things. And so I want to take a few minutes, and let's explore the this keyword. And we'll figure out how it works and what it does and what it means. And then we'll talk about some best practices around how to use the this keyword the right way. All right, so let's get started with an object. So, I'm just going to create an object. Just a plain old JavaScript object. And this JavaScript object is going to have a value associated with it. And this value is going to be just a string. Let's say, 'Hi there'. And it's also going to have a function. Let's call printVal, and it's just going to be a function. So, it's just going to do a console.log on val. Now, printVal has to have a way, a mechanism, to get a hold of the val variable on the object that it's part of. And the way we do this is using the this keyword. So, in this case, the this keyword is going to refer back to the object that's associated with it. So we'll just say this.val. So, when I run obj.printVal and I execute that, I'm going to print Hi there. So the this keyword is used as a mechanism to reach into the containing object for the variables, or the properties, that are on that object. Now, functions in JavaScript are first class objects. These are things that we can pass around and we can do things with. So that adds to some confusion. So, what if I had another object? And this object has a different value. Let's say this value is 'What's up'. Now, I want the printVal function. I just want printVal assigned to object two. So, obj2.printVal is going to equal obj.printVal. 'Cause there's no point in rewriting the function again. I've already got it up here. So I'm just going to use it on my second object. Now, when I call obj2.printVal, I have the this.value associated with the printVal up here in the object. But the this in this case, now that it's moved over, basically what we've done is we've, by doing this, is we've taken this and we've set it down there. So, the this in this case is going to refer to object two instead of object. So, the this here refers down here to object two. And I can prove that by running it. So, what that means is that because we can pass functions around, and because functions mean something different depending on where they're at, the way that JavaScript runtime works is it looks at the leading object. So, in this case, I've got obj2.printVal. And so, what the runtime does is it looks at whatever's on the left side of the dot and says this is the scope, that this scope that for this function. So if it's obj.printVal, I'm going to get this one up here. If it's obj2, I'm going to get this one down here. So, that's this works. That's ultimately what this is all about. This just reaches back into the object to help us figure out what to do. Now, that's cool right up until we start to do something a little bit different. What happens if I just say var print = obj.printVal? Now this printVal function is moved out to nothing. And I can just do print and run it. Now that I've moved it out, print all by itself doesn't have anything to the left of the dot. There is no dot. So, therefore, the this binding doesn't happen. It doesn't, there's nothing to bind it to. So what it actually does is it binds it to the global scope. So, just to prove my point, let's run this. And when I run this I get undefined. I'm still getting the What's up from down here. So I'll comment that out. But I get undefined, because this.val does not exist in the context of no object. And actually, just to even show you a little bit more, let's print out what this means. So I'm actually going to do a console.log on this, right here. And let's see, let's get rid of this one. And I'll only show you this, object2.printVal. What do you think you're going to see? Just think, just look at this. And say, when the this gets printed out, what do you think it's going to have in it? And just by looking at it, I'm going to have a val with a What's up, because we're in obj2. And I'm going to have a function called printVal. Because that's all of the things, the properties of this object. So when we run this, there you see. There's val, there's What's up, there's printVal, and it's a function. Now, if I come down here and I do this, and I run this print. So, this function is going to be run. But outside of the scope, there's nothing on the left side of the dot. So, I don't have an object to bind this print to. Now I'm going to run it, and look at this. I have this big, massive thing here. So, if I go all the way up, so, this is where it starts. DTrace server connection, a process, and all this stuff. So basically, what it does is if it doesn't have anything else to bind it to, it's going to bind it to the global scope. And so, the this in this case is the window. It's the global scope of your process. And in this case it's the node process. But if you were running it inside a browser it would be the window. It's just this global scope. And this is weird, and this not what we want. But this happens a lot, because there's some other scenarios that we can get into, and we will get into, where this doesn't really exist, but we think it exists. And we're binding it to the global scope. So one thing I'm going to show you right now is here's the other alternative to this. If I'm doing 'use strict', most of this module we've been talking about how 'use strict' applies to things, well, this is one way that 'use strict' applies. If I do print, and it's all off on its own, instead of binding up to the global scope, now I'm going to get undefined. See, I cannot read property val of undefined. So, this doesn't exist. Right here, when I execute print down here all by itself, this is undefined now, so .val doesn't mean anything. If I take off the 'use strict' and I run it, now I get the whole big thing. All right, so when I have no dots, nothing on the other side of the dots, so, in this case, right here, if I'm not in strict mode I get the global scope. If I am in strict mode, let's go back to being in strict mode, then it's undefined and it doesn't work. And it actually throws me an error and I know there's problem. All right, two more situations here. I can apply a scope. I can do a .bind on my print. So, I can bind onto the printVal. So, I can actually, right here, just do a .bind. This is the 3rd way that you can affect what this is. I can actually just bind this function back to object. Or I can actually bind it to object two. Let's just do that so that you'd know for sure. I've got object.printVal, and I'm binding that to object two. And I'm saving that function to this print function. And then I'm going to execute print. So, I'm actually going to print out What's up. So, even without assigning this printVal over to object two, I don't even have to do that. I've just got a function, and I'm binding it to this object so that when I execute this function, when I execute this printVal function, It's going to act as if the this keyword is object two. There you go. Now, that's three of the ways that this can be set. But the key being, always, how the function is executed is what matters. It's not where the function is created, that's irrelevant. The fact that this function is created inside an object doesn't matter at all, the only thing that matters is where the function is executed. If it's executed object2.printVal, down here, after I move it over, then it's going to be bound to object two. If it's just executed bound to object two, well, then that's what matters. If it's just executed without the .bind, then this doesn't mean anything, especially in strict mode. When we're in 'use strict', this doesn't mean anything. So, there's a 3rd way that this comes into play. And you'll see this a lot, actually. And this is where strict mode comes into play quite a bit. This in New Objects So let's create a new file just so that you can play around with this one in the exercise files. But let's do newobject.js. And let's create a function. So we'll just say var obj equals a function. And inside this function we've got this.hello = 'hello'. And we've got this.greet equals a function. And we'll just print out the greeting. We'll just print out hello. All right, now, here's my function, this.hello, this.greet. But it's a function, and so when I execute this function what's going to happen? This, as we've already said, is going to equal the global scope, right? So, that's weird and that doesn't mean anything. But actually, what's funny is I've seen this quite a bit, where people start doing this and then they'll actually just, well, actually they'll return an object with greet in it. And then they'll try and execute greet. They'll do object.greet. And it doesn't work, it's weird. And it's not even going to do anything. newobject.js, when I run that I get undefined. It's all weird, it doesn't even work. But I see people try and do something like this, thinking that it's going to make a difference, and it doesn't. But let's go back to our function, okay. So, I've got this .greet and we're going to say console.log, this.hello. All right, but what we're going to do now is we're going to say our var greeter equals a new object. So this is the 4th way that the this keyword gets dealt with. And so, var greeter equals new object. And in this situation, greeter is now a new object. And so the new keyword, when the keyword is executed, the first thing it does is it creates a new this scope. So now that I called new object, this actually has a scope. So if I just do a, let's see, let me just show you this. If I do a console.log on this, and I don't have the new, what am I going to see when I print this? I'm going to see the global scope. If I put the new on, now I have nothing. So, the new keyword binds a new this scope onto this function, that's what new does. Then it allows, so this.hello, this.greet, and then it also implicitly does a return this. Just like that. So, what that means is that I've got a greeter that is equal to just an object that has this.hello on it and this.greet. So let's actually, if we get rid of this, and I just do a console.log on greeter, that's what you'll see. See, greeter is now hello, and the greet function. Now I can just do greeter.greet. Execute that, and there I get my hello. Okay, so now I have this function. And I have, this function does stuff. And so now we're going to get into some best practices. Because this function may be an event that is fired. Now, I may hand this function off. So let's actually do that, let's hand this function off. Let's do a this.delayGreeting. And we're going to make that a function. And we're going to do a setTimeout. This is an easy way for us to play around with a callback. And we're going to pass into setTimeout, or this.greet. And we're going to set that for 1000, 1000 milliseconds. And then down here, we're going to call delayGreeting. Now when I run this, check this out. I get undefined. And that's weird, because this is obviously this.hello. This is the object. It should just work, but it doesn't, and I get undefined. And here's why. Because in my callback, setTimeout isn't calling object.greet. It's not calling, remember from over here in this file, it's not calling object2.printVal. It's making a copy of printVal, just like that, and handing it to another variable. And then it's just executing that variable. So, somewhere in setTimeout, there's a, so, if I setTimeout equals a function, then it takes a callback and a value. And it just does cb and executes it. Well, since there's no dot, we know what happens. It gets a global scope, and that stinks. That's not what we want. So there's two things we can do here. There's a painful way and a less painful way. And so, this is where we kind of get into best practice. So, if I go to this and I add this .bind, right, and so every time I do a callback, I pass in this .greet and I bind it back to this. I pass that in, hey, look, it works. Because I'm binding the function to this. Now, every time you do a callback, and every time you're going to pass something into a callback, you have to do .bind and that kind of stinks. And that's not a lot of fun, so let's not do that way. Let's do it this way. Let's actually take a copy. And I can say var_this = this. Now I'm not referencing the this keyword anymore. I'm referencing _this. And I can say hey, everywhere I referenced this, I'd just reference _this and it's all good. Now when I call .greet it's not looking for global this. Or the this context. It actually is executing a specific thing. And that allows me to maintain my hello. My reference. So this is what you'll actually see a lot of people do. When you're creating an object and you've got a constructor and this is all working, if you take a copy of this up here at the top, when you're creating your variables, if you're in Angular, I do this a lot. If I'm in Angular and I'm creating something for my controller, I'll just call it ctrl, my controller equals this. Or you might see it as a vm for view model. My view model equals this. And then it references the view model all throughout. And that's why, so that you don't lose your this scope over the course of the thing. All right, so that's this. And hopefully that was helpful to kind of help you understand what this does and where it comes from and all that kind of stuff. But to, ultimately, the best practice of. When you're dealing with the this keyword, it is easier to just take a copy of it and use that copy throughout than to try and always figure out what this might reference at this point. Because here, we're not referencing this. When I've got _this here, I'm not referencing this wherever I'm at. I'm actually referencing this very specific thing, which is for the object. Summary So, in this module we started talking about some JavaScript behaviors. And we kind of carried over from our syntax conversation. And went more into how JavaScript behaves, and some of the weird things that it does that you may not expect it to do. So, we talked about strict mode and how strict mode's going to protect us from that. Whether it's, you know, octals when I don't expect octals, or I'm trying to delete things that I can't delete, or overwrite things I can't overwrite. Strict mode is going to give me clean errors. It's actually going to say, "Hey, this is a problem." Instead of just burying errors underneath the covers and having me not know that something is actually wrong. So, the summary, really, of this whole module is we're going to use strict mode. If the best practice here, when you're dealin' with JavaScript, is turn strict mode on, turn strict mode on like we talked about in, I think it was clip three, turn strict mode on inside the context. So that you're not causing errors in package code that you're downloading off of the internet. But use strict mode so that you know what's happening, and you don't get caught up in unintentional problems, because JavaScript wasn't throwing errors that you were expecting it to throw. Async Patterns Introduction Alright, so in this module we're going to talk about Async patterns or some ways to deal with asynchronous code that's executed in JavaScript. And this is usually kind of a pain point for a lot of people who are entering JavaScript development because it's just so different than everything else that's out there. And so what we're going to talk about is these Async patterns and how to deal with asynchronous code. We're going to start by talking about callbacks and callbacks are usually where people become frustrated with JavaScript and they start to throw in the towel and say, "This is stupid", because you get what they call "callback hell" or "Christmas tree code" or just really gross looking code as you're dealing with callback after callback after callback. We'll look at some good ways to write callback code but then we'll also add in some promises and we'll talk about the way promises work and how they help separate out your parameters from your function code. And last but not least we're going to look at async, we're going to look at the Async/Await that's coming in up at ES7 and how you can start to implement the Async/Await pattern into your code today using a transpiler called "Babel". Callbacks Now, the first pattern I want to talk about is callbacks, and if you've been doing JavaScript for any length of time at all you've hit callbacks, and callbacks can often times be painful and they're not the easiest thing to follow along with when you really get going. In fact there's a term out there called "callback hell" that refers to the fact that sometimes we nest callback after nest callback, you end up with some Christmas tree looking code that is difficult to read and difficult to troubleshoot if you run into problems. So for this clip I have gone back and I have dug out the code end from module 7 of my WebApps course. My WebApps with no JS and express. And I'm using this code specifically because it's real code and as we go down through it you can see kind of what I'm talking about. So, we've got a function and then we've got a function and then we've got a function and then we've got a function, and all of this basically to just check to see whether the password for a user equals another password. But if you just look at this code it's very difficult to read, and actually I've got my line up at two spaces, most people have this set to four spaces, I'll change this to four. And this is the Christmas tree code that everybody talks about, just, it looks horrible and is not exactly the way you want to do it. So I want to show you an alternate way to do callbacks. A lot of people will point to promises, and we'll talk about promises here in just a little bit, but those don't necessarily solve this problem. I'm going to show you a different way to do callbacks that's a little bit easier to follow, and we're going to do that using named functions. Let's change this back to two so that it's a little easier to see everything on the screen. Now, the first rule I have for callbacks is nobody ever said that you had to use anonymous functions. For some reason we've gotten to this havoc, because it's easy, of just anonymous function after anonymous function, and one way to help break ourselves out of this callback hell, if you want to call it that, or Christmas tree code, is to stop using anonymous functions. So I'm going to take this function right here, let's go all the way down at the end of it, and I'm going to cut that out, let's just get rid of that. Got the passport.use on this and what that's doing is not really relevant to this conversation, but just know that this is what passport is going to use to validate the user, needs to findAndValidateUser. So now this is a lot easier to read. So passport.use, we're going to pass in the username and password, and then we're going to find and validate the user. So that's easy. And remember, back to module 2, we talked about syntax, so a best practice says here is my var with my variables, the very next thing we want to do is functions, so we'll set our function. Now, what I can do though, right here, I just paste what I pulled out, and say this function is called findAndValidateUser. So now I have my findAndValidateUser, I still have a bunch Christmas tree code, we'll deal with that here in some minute, but when I actually get down to the code that's running, so module.exports = function, we're going to do a passport.use and then we're going to find and validate the user. Done, this is already easier to read and easier to understand what's going on just by naming this big, massive anonymous function something along the lines of what it's actually doing. Alright, now let's follow this out to its conclusion so we can kind of see how everything ends up. The next logical step would be to take this function, so we're connecting to MongoDB and then we're executing a function, and we need this whole thing pulled out. Now, notice at the end, so when everything is all done, the center of our Christmas tree, we're executing this done. So the whole thing is going to need access to this done callback, and that callback comes from right here, inside this initial function. So what we can do is, when we pull this function out, this whole big thing, so we'll start there and cut the whole thing, so mongodb.connect, and then we're going to find user, and findUser is going to be a function. So back to our best practice from earlier, right? I've got my var url, then, because I need access to this done, I can put this next function inside this function, so findAndValidateUser is actually going to have all the rest of the functions inside it so I have access to this done callback that's originally passed in to the initial function. So we'll just paste that function right there and this function is going to be findUser, function findUser (err, db). Clean it all up. Already we're looking much better. Alright, findUser goes out to the collection of users, does it find one? And then gets this function. If we pull the whole thing, we'll just cut that out, this function is going to validate user, boom. I will put that function up here, validateUser, and then validateUser is going to take the results and work through that. So now, what we end up with? If we look, so we start with what this localStrategy does and we come down to the bottom, we're exporting a function that's passing in the passport.use this localStrategy, and it's executing this function validateUser. What we had before, if you remember, looked like this. So we've got this module.exports and then our Christmas tree. And actually I keep it on two but if I put it on four, our tab size, on four, which is where most people have it, it looks really bad. So, this is what we had before with anonymous functions and things looking kind of gross, when we name our functions and kind of move everything around now we have, we've gotten rid of our Christmas tree. We've got some functions, findAndValidateUser, validateUser, findUser, and everything's all bundled in just like that, which is exactly what we want. Now, the next piece of this is error handling inside because we're not doing any error handling in here. And one best practice around callbacks, and this is mostly because I come from a NodeJS background, if you don't come from a Node background or you don't work with Node, this might be a little different but I really like the pattern that is used most often in Node when it comes to callbacks, is notice when we execute a callback it's err and then the results, err, results, all of them work that way. And so what you can do, let's go to the first one, findAndValidateUser, we're opening a connection, so we'll follow this up so that we can just see it, mongodb.connect and then we call findUser. So findUser, if we don't connect to the database, if there's an error, we can right here call done and exit out of this whole loop, everything is gone. And same thing with validateUser. Now, I know if you're a stud you'll know we're not really done but we'll fix that in a second. Then I do my findOne and I go to validateUser, so now I come to validateUser. If err we can call done with err and null, and clean that up. We can do this done callback, so the original callback from our original function, anywhere through all of these named functions, anywhere we have an error we can just call done and pop out of the whole thing and be done with it. Alright, now here's an important thing, when you're dealing with callbacks and you are executing a callback, so in this case done is a callback, so right here, I'm done, err and null. When you're executing a callback, in your mind, 9 times out of 10, most of the time, in your mind you're thinking you are done with this execution. So when I call a callback I want to be done, nothing else is going to happen inside this function, and so a good practice, if not a best practice, is when you're executing a callback, so in this case done is a callback, when I execute this callback, it's a good idea to return at this point. So, anytime you're calling done we're going to call return so that I know I am ending everything, everything's done and it's over. So everywhere I have done I'm going to return and that's going to be what we want to do. So, when it comes to callbacks here's your best practice, we want named functions, get rid of your anonymous functions, they're just confusing, they lead to the gross Christmas tree code, they lead to this, this is horrible and gross and not what you want. Move to named functions and you get this, it's much easier to read, much easier to see, and it's much easier to know what's going on because now I can just read the name of the function, findAndValidateUser, findUser, validateUser, and know what's going on inside those functions. Second, you've got "err, results", you have a pattern for how you deal with errors and how you pass errors back from callbacks. If you're on the NodeJS side that's "err, results", if you're on the front-end side a lot of times it'll be something a little bit different but I don't want to go into all the different patterns that we have for that type of thing, but find what works in the environment you're in and be consistent, back to module 2 when we talked about consistency being key. And last, third, is return your callbacks, so if you're calling a callback just put return in front of it and that will pop it out and then you're done. Alright, so that's callbacks, let's move on to something else. Promises So callbacks almost get us there, not quite to where we want to be, so let's take one more step and look at promises. Now, promises are built-in natively to Node 4 but they're not native in most browsers in JavaScript. So let's take a look at promises but we'll do it a little differently, we'll do it using the browser instead of what we've been doing all along in the command line. But the thing that promises do for us is that they extract that callback function from within the parameters that we're passing to a function, and allow us to separate our concerns a little bit. So let's take a look at this and see what we can get going. So here we've got an index.html that just says, "Hey, 'Lets Talk Promises'". And what we're going to do with this is we're just going to run live preview in brackets, and when I run live preview in brackets it's basically just going to give me this, "Lets Talk Promises". And we'll do everything else in the console just kind of like we have but now we're in the browser instead of command line. So let's go over to app.js and let's start doing some stuff. Callbacks and promises come into play when we're doing async methods, and so what I'd like to do is just for the fun of it, we're going to create a function called asyncMethod, and this asyncMethod is going to take a message. Basically how we're going to replicate an async method is we're going to call setTimeout, and what setTimeout does is wait, let's say, 500 milliseconds, and then executes whatever function goes right here. So we'll just do a function, and this function is going to do a console.log(message). So basically what we've done here is we've just replicated an async method without doing anything complicated. So this could be a call to the database or, well, in the browser a call to an API or things that we can do that end up being these weird asynchronous Christmas tree calls. And now let's add some calls. A good example of this, let's just reuse the same thing we kind of talked about in callbacks where we've got to call an async method that will find the user in the database. Actually, let's start with "Open DB Connection". Alright, so now we need the callback, so let's come up here and do a callback, and at the end we'll execute the callback. So now I've got a callback so I've got a function, and in this case let's do asyncMethod, after we open the database connection we'll find the user in the database and that's going to take a function. Don't tell me we haven't done this before. Then we're going to call another asyncMethod that's going to validate our user. Let's going to then call another async function that will do stuff. And then we'll be, and then we just have to pass in a function even though we're kind of done. So this is that Christmas tree code, right? That everybody complains about. If you build these functions out a little bit more it becomes really, really super gross. Now, if I pull this back up and we open our developer tools if I refresh, we see "Open DB", "Find user", "validate user" and we "do stuff". So this asyncMethods are working and they're gross and they kind of stink, so let's fix this using promises to kind of make this better. We're going to do that by using a script from promisejs.org, and this kind of gets into how promises work and all that, and I'll walk you through this here in just a minute, but let's scroll down to, down here close to the bottom they have "Browser" and a script tag that we can include to start doing promises for our code. So we're going to copy this script tag, "promisejs.org/polyfills/promise-7.0-4.min", all that, and we're going to drop it into our index.html. Alright, so that is now there, let's go back to our app.js. And what that's going to allow us to do is here in our asyncMethod it's going to allow us to return a new promise, so we're going to do a return new Promise. And this promise is going to take a function, and this function is going to take two parameters, it's going to take fulfill and reject. We're not going to do anything with reject for this course but I just want to let you know that it's there. So basically it's, fulfill means our function worked, reject means it didn't. So we'll get into that, okay. Now I take this and I drop it up there, just like that. Okay, so now instead of callback we're going to execute fulfill and we'll take our callback out. So basically what we've done, all this promise has done, is it has taken our callback, which is now called "fulfill", and pulled it out of our parameters. So now this becomes this. That is essentially what a promise does, a promise makes our functions thenable. So we have our asyncMethod, we do something then we execute a function. So if I save this and we look at our promise code again and I refresh everything still works exactly the same way but now is .then. Now, you may look at this code and think, "Well, this is dumb" because this actually looks worse than what we had before, because now we've got this big ".then" sticking out in the middle of it, and, you know, you can do stuff like this, you can put your .then down on the next line. And, you know, God, actually still looks kind of gross. So what we do is we combine what we were just talking about with callbacks in getting rid of these anonymous methods. So what we're going to do is we're actually going to pull these out. So we're going to start with this, we're going to pull that out, and we're going to call this "findUser", and we're going to say function findUser is that. And then we're going to take the next one and this is going to be validateUser. And we'll take the last one which is do stuff and just call it doStuff. Alright, now we've got asyncMethod findUser, then validateUser, then doStuff, then our last function. We'll save that and we'll refresh this. There we go, everything's still working. And this is a little bit better, it looks much cleaner but it's not even quite what we want, we're going to take this one step further, and this next step is where things become interesting with promises because promises are essentially, it's an object, right? It's just something I can do, so I can actually return a promise. I'm returning it here but I can go ahead and return it again, so instead of this .then being here I can pull that out and I can return the promise to here. So now I can do .then(validateUser) there. And I can return that promise here and do .then(doStuff). And I can return the promise there and now look at this, this becomes much cleaner. So I've got my asyncMethod and once you get rid of all, let's fold up our functions. Look at this, I've got asyncMethod, open database connection then I'm going to fin find the user, validate the user, do stuff and then we end. If I refresh, look at this, everything still works, and tell me that that is not so much cleaner than the gross code that we had before. The end result of this is that now we just have chain of thens and everything just works right. What we didn't talk about is this reject up here, and the reject up there is like the err side of the callback. So findUser, we can do .then, findUser or error, I have an error function that handles our errors for us. So that's the other side of it but I just wanted to give you enough of a push to say, "Hey, check promises out". Now, promises are not available natively on the browser so we're running them through this promisejs. They are available natively in Node, if you're using the newer versions of Node, promises are there, but I don't want to stop there. Let's talk about Babel and transpiling, and then let's take a look at ES Next, and using Babel we can get into ES Next and start talking about really cool things like Async/Await. ES6 and Babel Now before I can talk too much about the async stuff that I want to talk to you about we have to address ES6 first because actually the async stuff we're going to talk about it's even ES7 and so that's like not even close to here yet, but we can still use it because we have a cool tool called Babel. And when we're talking best practices there's a lot of cool syntactic sugar that comes along with ES6 that we could be using in our code today regardless of the browser, as long as the browser supports ES5 we're fine. So, let's talk about Babel real quick, and what we can do to kind of fix our code and some of the issues that we run into. Now, the feature list involved with ES6 is really extensive and I don't want to turn this course into a conversation about ES6 in general, more about the fact that you can use and should be using ES6 code. There's a lot of courses out there already, and just a lot of Internet references around what the feature set is involved with ES6, so I'm going to show you just one, I'm going to show you scoping, and then if that picks your interest then you can use Babel and you can explore ES6 a little bit more in depth. Well, let's go back a little bit to the issue we had with scoping before. And once again, I'm going to do this in the browser, so using index.html where we're pulling in app.js, and I'm doing this because these functions are native in NodeJS. So if we're running in Node and you're in strict mode, which you should be, best practice, alright, if you're in strict mode and you're in NodeJS you already have access to a lot of ES6 features, so there isn't this extra step that there is on the browser side, and that's what we really want to talk about here. So we want to talk about that extra step on the browser side using Babel. So, let's go back into our app.js, and let's just do something simple, so let's do just a for loop 'cause this falls into what we were talking about. So let's just say var i = 0, i is less than 10, i++, and we'll just print that out to the console. Now, if you're coming from another language you may think "i" is safe. When we talked about, we've talked about scoping and we're not going to rehash that, but I can right here say, "Hey, 'I see i....'" and if I put a "+ i" there when we run this code, we look at our console, you see "I see" 1 through 10. So it's 0 through 9, "I see i ...." and i equals 10. So we don't like that. Really want to use the let keyword because the let keyword is going to allow us to hide that i from everything else, and so the point of all of that comes down to we can use Babel to compile down our var, so we can use let, and still use that in the scope of ES5. So, here's what we got. If we go to our command prompt there's two things we need to install, we need to do an "install -g" on babel-cli and then we need to create a file called .babelrc. And this babelrc file basically just looks like this, it's just a JSON file that says, "Hey, I've got presets and plugins", and for right now our presets are "es2015". And so what that preset's going to allow us to do is compile ES2015 code down to ES5. So if we run back to the command line we also want to do "npm install", I'll make that a little bigger, "npm install babel-preset-es2015". And when we install that that will now give us the preset for Babel so that we can run our code because right now, while that's installing, right now if I use let, and I'll actually show you this on the Safari side 'cause Safari is actually worse, if I refresh this page you see, "Hey, 'unexpected identifier i'". So it doesn't know what to do with this let keyword. So that's broken, which is what we expected. So I've got my app.js with my let keyword, Babel's done, so now what we're going to do is we're going to type "babel app.js -o es6.js". And what that's going to do is convert our app.js file to code that is runnable inside ES6, and we can do this with all of the ES6 commands, so like class and Arrow functions and all of that stuff, we can now use and we just do Babel to transpile it down. So now if I go to index and I change this to es6.js what we expect is now we get "i is not defined". And if we go over here and I refresh, look at that, "can't find variable i". So now that's how to get up and running with ES6, we've got Babel, Babel CLI, you can wire up Babel into Gulp or Grunt or whatever build process you use and compile all of your ES6 code down to ES5. So now that we've got that now we can talk about async, which is actually not even ES6, it's ES7, but Babel will still work for us. Async - Await Alright, so coming up in ES Next is Async/Await, and what this does is kind of eliminate the need for callbacks and promises and all that with the way it works. And so let's take a look at how these functions work and how we can start using them now. Alright, so to start with it's still based off of a promise, so the Async/Await mentality still works off of the promise principle, so our asyncMethod is going to remain unchanged. It's going to still return a new promise and everything is going to be fine. But what we want to do now is create a new method and we're going to create an async method called main, and we're just going to run everything through this main method. And we're going to take all this stuff and we're going to drop it off in there. And then we're going to call main and execute that. Now, what the async method allows us to do is to use a keyword await, and what await does is eliminate the callback, it basically is going to sit and wait for this async method to continue or to be done before it continues. So, actually, we'll just do this, var one = await asyncMethod, and so what used to be passed in a callback now gets passed into this variable, and we'll just do this. We'll create a bunch of these, just three of them, and we'll get rid of our .thens. And this will be "two", this will be "three", and this will be "four". And let's pass to our methods this way. And our last one. And then we'll get rid of all our functions, and now we just have this. So basically it's each variable await asyncMethod, I'll pass our awaits on them. So basically now what we have is await asyncMethod open a database controller, await asyncMethod find the user, and it's just going to execute this in order. Now, just so you get an idea, we haven't been using variables in our callbacks, so just so you get an idea of what this is going to look like let's change our asyncMethod to take a number, and our number is actually -- So we do a console.log(message), we'll just add that number to the end of it, and then when we call fulfill we'll just increment the number. So we say, "Hey, 'Open DB Connection 1'. 'Find User 2'". And we'll pass these variables in so you can see how that works. And this first one we'll just pass a 1 in, or we'll pass a 0 so you can see it. Okay, now, basically what that means is, "Hey, whatever gets executed in this callback "gets assigned to this variable", and then I can use this variable in my next call. This is cool if it works, and so we got to get there. The first think we're going to do is we're going to create our new file .babelrc. And our .babelrc is going to look extremely similar to the last clip. So, "presets", "es2015" and "plugins". Now, here's the deal though, in ES Next we're not talking about ES2015, and so what I want to do is I want to take you to a website that you should become very interested in, and this is a compatibility list of all of ES5, 6 and Next. So if I look at 6 you can see what features, so for example the Arrow functions that we haven't talked about yet, or Map or Typed Arrays, and you can see what browser support what. And notice Node 0.12 doesn't support a whole lot but we get up into Node 5 now all of a sudden we've got a bunch of green. Babel's the same way. So if we go to ES Next we can see where our function support is, and so if we look at async functions Babel core supports them. And they support them in something called Stage 3, and just real quick, 10 seconds or less, Stage 0 means these are things that we would like to support sometime, Stage 1 is proposed, 2 is draft, Stage 3 actually has a pretty darn good chance of getting included in a next version of ECMAScript. And so they've moved away from, I sometimes use interchangeably ES6, ES7 and 2015 and Next and ... That's fine, some people get better shape, it's okay. But ES Next is going to potentially be ES2016, right? Maybe, if it gets done. But then we have Stage 3, things to get included, and you'll see async functions are in Stage 3 and they have basic support for await. So what that means is we have to pull in the Stage 3 preset. So once we've got the "stage-3" preset we need to install it, so "npm install -save babel-preset-stage-3", we'll run that. And then once that's done we'll run our compiler. So "babel app.js -o esNext.js". Now, just for simplicity sake we're going to just leave it there and so one thing we need to add to our app.js is 'use strict' because we're going to run this in Chrome and this is going to pop up a lot and I'm just going to let it go because we can, so we'll do a 'use strict' instead of trying to pipe it through a whole bunch of other stuff. There we go. So that has run and we go to our index and now I'm pointing to esNext.js. So we're going to run this. And when we look at this now you look and see 0, 1, 2, 3, that's exactly what we were expecting. Let's refresh. 0, 1, 2, 3. So what' we're getting is this asyncMethod('Open DB Connection') returns 0 + 1, and so now this variable "one" actually contains this. And so that's kind of how async works, it's just a quick little look, a peek into the feature, if you will, of what's coming for callbacks and promises, and we're going to end up in this Async/Await style which is kind of what like everybody else does. Like if you do .NET you just wait for it to come back, and so that's kind of what it's implementing here on the site. Summary So in this module we started talking about Async patterns or JavaScript and the way JavaScript works around asynchronous code. And we started by talking about callbacks, and that callback hell or Christmas tree code that occurs in a lot of JavaScripts where you just get callback after callback after callback. And the first thing we talked about, when it came to best practices, was using named functions. If you name your functions instead of passing anonymous function after anonymous function it helps alleviate that Christmas tree code that you get so that it's much easier to read what's going on. Then we talked about promises. Promises is the next iteration, so if you take your named functions you still are passing a function into your parameters of your method, and that's not really ideal. Promises help you pull that out and you get the .then syntax that you can use in your code just to make it a little cleaner, a little easier to read. Then we took a quick break and we talked about Babel and using ES6 in our code. So we can write ES6, we can transpile it with Babel, and everything just works great. That gives us access to, using Babel gives us access to this cool Async/Await structure that's coming in ES7. We can do it now using Babel to transpile down from ES7 so that now Async/Await says you can get rid of callbacks completely if you want to, you don't have to but you can if you want to, and that can make your life so much easier knowing that if I don't have to wait for something to come back, and I don't have to use that function for the callback, I can just have it return a value and that makes everybody's life a little bit easier. So that's it for these Async patterns. There's one module left, and this one is important because our code doesn't run only on our server, at some point we have to deploy our code up to production, and so I want to talk about some best practices about deploying your JavaScript code to a production environment. Production Code Introduction In this module we're going to talk a little bit about production code and having code exist in our production environment and we're going to focus on Node.js in this case because that's where a lot of these gotchas are going to get you. So we'll talk about some Node.js best practices and we'll talk about things like npm and so the best way to use npm and how npm works a little bit. We'll talk about setting up our environment. Instead of just hard-coding everything, we'll have some environmental variables and we'll pull out of the environment. We'll talk about some cross platform gotchas. Node's awesome for cross platform, but Windows is not Mac is not Linux and so we'll talk about a couple of the gotchas that come from being in a cross platform environment and we'll end with a conversation about simplicity. Really what I want everybody to walk away from here is to simplify their JavaScript a little bit. Things have become kind of out of control and spiraled into this big monolithic thing and I think this year especially we're going to start to simplify our JavaScript quite a bit and we'll talk about that also towards the end. NPM Settings So the first thing involved in getting your Node code production ready is npm and using npm in the right way and there's a couple of tricks I want to show you that may help in getting you ready for where you want to go. So let's start. I am in a new directory, basically I just have my app.js file, and I've got my app.js just console.log('hi'). It didn't really do anything. But the first thing you want to do always, and you probably already know this, the first thing you want to do always when you're creating a new Node application is nmp init and what nmp init is going to do for you is it's going to create your package.json file and your package.json file is actually really important and we'll talk about all the reasons why here in just a minute, but to get it up and running and do it right, just take the defaults, there you go, let's set up, it's ready, and now I have this package.json file that I can use to get some stuff done. If you're lazy, delete that, and you do a --yes, oh look it's done, you don't even have to hit Enter, you don't have to do anything. Okay so there's my package.json file and there's two things about my package.json file I want to talk about right now, first and foremost, and the first one is dealing with the engine keyword. Now you may not have seen this, but basically I can say hey I can set my engines or the versions of node that I am allowed to run on. So in this case, let's just do this, let's do 4.2.1. I am running currently 4.1.2 and this wants 4.2.1 so in theory my code should not work 'cause I can just say hey everybody, I am only allowed to run on version 4.2.1 of Node. Now you can do the same thing with this that you can do with your nmp packages, or your dependencies, you can do the tildes or the less thans, I can only run on things that are less than 4.2.1 and that should work. Now what this does is says when I'm a package, when I'm installing something with a package.json, it checks this engines and let's us know whether or not it's okay. So in order to see that, we're going to do a cd .. and then nmp install code. So I'm installing this thing I just did and I'm going to get a big, huge warning that says "Hey, Node 4.2.1 is wanted" and I've got 4.1.2 and npm 2.14.6. So everything's old and so it's bad. So that's a way for where you just to say hey this is only for Node 5 or this is only for Node 0.10, right. Node changes fast and it's really a good idea to wrap some constraints around your code to make sure that if somebody's running bleeding edge Node that your package isn't going to work on that they get an error saying hey this isn't going to work. Alright, one other thing that I want to talk about when it comes to npm packages is if I'm sitting here and I'm in code and I do an npm install express, I'm going to install Express, it's going to go into my Node modules, oh it didn't get into my package.json. Hold on, so we got to go back, save 'cause you always do --save because it's going to pop into this directory and now I have my dependencies and so basically what this says is hey anything that's close to 4.13.4 go ahead and install and there's two problems with this. One, I'm lazy and I want to keep things simple as possible and the --save is offensive to me because if I'm doing nmp install, I know that I want it there. Almost never do I do an nmp install on something inside my application and not want it to be saved. So the --save is this unnecessary extra thing that I have to add when it should be implied and also I don't like the idea of the caret because my code and especially we've seen some issues where package developers are deploying breaking changes from one minor version to the next and that's not cool and so I don't want it to default to this caret. So what we can do is set two command line parameters for nmp that will solve a lot of these problems. The first one is this. So we'll do an npm config set and we'll set save equals to true. Now just by doing that, if I do an nmp install passport and I run that, look it saved it automatically. No more --save for every single thing that I'm trying to do an nmp install on. But I still have the caret and I don't like the caret because I don't know if I'm going to work with 0.3.3 or 0.4.0. I want to use the version that I know I work with and just use that version and when I have tested a new version then I can change my dependencies and so let's fix that as well. So here you're going to do instead of save=true, we're going to do save-exact=true. Now if I do, we'll just come in and we'll delete these two, save that, and I'll do nmp install passport, nmp install express, look at that, there they both are, the exact version saved, I didn't have to do --save, I didn't have to do any of that. So that's setting up your nmp environment. So now I've got nmp, I've got my package.json file, it's done, it's set up, I've got my dependencies being tracked. When it comes to best practices for deploying production code, this is the start of it. Right, so I've got a file here that says this is the way it's going to be, this is my code, this is the version, this is the version of Node I run on, here are my dependencies. You don't have to worry about whether you forgot to do --save on that one. That's no longer a concern for you. Environmental Variables The next thing we're going to talk about is the environment that you're running in because some things are going to be different between where you're running in Dev versus running in QA versus running in production and one of those things might be your database connection strengths, that's definitely going to change, or your port that you're running on, that could change, or there's a lot of other potential things that will be different from one environment to the next and one of the easiest ways to do that is to use a tool called Node Foreman and we're going to get into how to work with that to get your environment set up to be different from one thing to the next. So back to my application here and I've got my app.js and when we start up an Express application specifically, we always run it on a port and the standard thing that you see a lot is now you see Express listening on port and then a port number and where we want to pull this port number form is from our process, process.env.PORT, and that's ultimately what we want to do is we want to, after putting a plus in here, we want to keep our ports and our connection strengths and all those things in our environment and let everything else deal with it and the way we're going to do that is we're going to use a tool called Node Foreman and Node Foreman does a lot of stuff for us. It can set up worker processes and do all those things, but right now we're going to focus just on the environmental variables and the first thing we want to do is do an nmp install -g foreman and what that's going to do is allow us to use the NF command to run our application for us and what Node Foreman's going to look for, if we go to our package.json file 'cause remember everything comes back to our package.json, is it's going to run a script. So if I say start, our start command is going to be app.js. So now I have a script called start that's just going to do node app.js because app.js is the script I want to run. And so now if I do nmp start, it'll run and you see right here listening on port: undefined because it's not there, right. But if I do nf start, which is Node Foreman, Node Foreman is going to run that start directory and hey look, Express is listening on port: 5000. Isn't that weird, it has a default to some of these things. And so it's automatically setting our environmental variable because it didn't find, no ENV file found, it automatically set some stuff and so let's fix that. So right-click, new file, ENV with a dot in front of it, .ENV, and this is going to take a JSON object and we're going to say hey our port is going to be 9000 or I could say our connection strings, our sequel one and our mongo one. We can do all that stuff right here in our .ENV file. And now I can get to that or Node Foreman will automatically take everything in my .ENV file and stick it in my process.env. So if I run this, nf start, hey look, Express is listening on port: 9000. So make sure that as we're writing our Node code and we're building out our applications, we're pulling in environmentally specific things using our process.env and then we use a tool like Node Foreman, you could use Nodemon or a couple others, to set your environment. But Node Foreman, what it will do, it will set your environment and get it ready to go so that when you deploy to production and you do nf start in production, you're pulling in your .ENV from there instead of whatever you're running locally. So just a simple little thing you can do to make sure your code is doing the right thing in production without having to do some weird hack to make it work. Cross Platform Concerns One thing that's easy to forget is that Node.js is truly cross platform, it can run on Windows, it can run on Mac, it can run on Linux, all of that full across the board and sometimes that comes with a couple of gotchas and I want to show you one of them real quick. I'm going to create a new file called myObject.js and this object is going to do a module.exports and we're just going to send back an object that says hi: 'Hello there' and we're going to go back to our app.js and we're going to say var myObject = require('myObject') and then instead of console.logging our port, well we'll still do that, but we'll also CL myObject.hi because myObject.hi is hello there. Alright, if I run this, everything breaks because I need my dot slash. There we go, alright now let's run it. And of course, not my semicolon. We know I talked a lot about semicolons, well don't use it there. Okay, now we ran it and I said hello there. So this seems extremely straightforward, I don't know why I'm wasting time with this. Right, so I've got my myObject, my myObject, all that's cool, everything's great. If I rename this to myObject, actually in order to get it to do it, I've got to cut that, I've got to do a delete, don't save. I'm going to do a new file, myObject.js, paste that. Oh look, now when I run it, look how it still works, myObject lowercase, myObject uppercase, it all worked. This is where you start to have problems with cross platform because in Mac and Windows, this myObject and this myObject are the same thing, but on Linux they're different and so the best practice here when it comes to making sure everything's cross platform able, one of the first things you do is everything's lowercase, your file names are lowercase, this is lowercase, and if you're actually doing a full-blown package, it'd be more like this. A lot of us are used to doing the camelcase. Well, we don't do that, we do this because the camelcase, if your file name's aren't correct, can cause you problems. So just little snippet there. Make sure that everything is lowercase as appropriate and you can do the dash casing, there you go, to make sure everything's going to run appropriately, right. So that's that for the cross platform, making sure everything's going to work. Just be aware that Linux, especially with file systems, is going to be a little different. Windows will have its own idiosyncrasies, but just be aware. Simplify Your World Now the last thing I want to talk about here is the keep it simple rule, the KISS approach to JavaScript and what you've seen pretty much everywhere is this massive grouping of tools that have come about into our JavaScript environment and you will notice that I did not cover a lot of things as we come to the end of this course. I didn't talk about a lot of stuff that a lot of people would say hey this is best practice, you better use gulp or you better use grunt or you better use this tool or that tool or all of these things and I'm saying no, that's not best practice. If you have a problem that can be solved by using gulp, use gulp. If you have a problem that can be solved by using bootstrap or by using angular or something, that's cool. But what we have discovered is that a lot of people are spending more time trying to get gulp to work than it would be just to keep doing the one thing they were doing before to help with that and so I'm picking on gulp a little bit, I use gulp, I love gulp for the things that I use it for, but I want you to really pay attention to and the reason why I did not talk about a lot of things that I could have talked about in a best practices course is that don't confuse getting things done the right way and the simple way and the best way with using a tool or using some extra thing. So I really, truly believe that we're going to start to see a shrinking, especially over the next year or so, of the complication around JavaScript development. I think a lot of these big monolithic toolsets and some other things that are going on are going to go away a little bit and will shrink back in and that's my opinion and it's not necessarily the prevailing opinion, , although I think quite a few people would agree with me, and so just as we end this course I want you to think about keeping your code simple and keeping your environment simple and not using things 'cause they're cool, but using things because they actually are helpful to you and so with that, that's it for the course and we covered a lot of stuff and I hope that this was helpful and you learned something, one or two things, and that would be great and just keep that whole picture in mind. Do things the right way and it'll make your life so much easier. So thanks for hanging out, thanks for watching. If you have any questions, hit us up down in the discussion. Other than that, check out one of my other courses. If you're interested, I've got a Node one out there, I've got a design patterns one out there. Those would be great too, thanks a lot. Course author Jonathan Mills Jonathan Mills is a JavaScript and Node.js expert working mostly in the MEAN Stack with individuals and companies to help build their technical skills to cope with the constantly changing landscape... Course info LevelIntermediate Rating (441) My rating Duration2h 39m Released5 Apr 2016 Share course