What do you want to learn?
Skip to main content
by Elijah Manor
Start CourseBookmarkAdd to Channel
Table of contents
For the rest of this module we'll focus on bugs that relate to statements. So, let's get started.
Missing Mark Bug
Missing Mark Bug: Demo
Fresh Function Bug
Fresh Function Bug: Demo
Tumble Through Bug
For this tumble through bug, we have a getPrice function that will return whatever price we've defined for the fruit we've provided. Can you spot the bug? (Pausing to spot bug) The answer that we get is that passion fruit is only $0.50, which it should have been $1.50. This one may or may not have been easy for you to spot. If you see a switch statement, one of the first things you should look for is if all the break statements have been provided. If not, then you could possibly have a bug on your hands, unless it was intentional. In this case since there was no break after price = 1.5, it fell through to the pear case and set the price to 0.5. Since it has a break, the flow of execution removed to the return and we get the incorrect value. Thankfully JSHint will warn us about such things. Here's an error that we receive if we forget to provide a break inside our switch statement. Switch statements typically have a break statement after every case so that they don't conflict with each other. Since leaving out a break can cause a nasty bug, that's why there's a test case inside of JSHint to warn us when we've forgotten to include one. However, what if we meant to leave out a break? There may be times when you intentionally want a case to fall through multiple clauses. Thankfully there's a way to tell JSHint that you want to do this. All you need to do is provide a falls through comment where the break would have been, and JSHint won't complain. So in this case, the easiest way to fix the issue is just to add a break right after providing the price for passion fruit. And there you go, the code works just as intended. Another possible solution for this problem would be to not use the switch statement at all, but rather use an object to store the prices. What we'll do is have the keys of the object represent the fruit names and the values represent the price of each item. In addition we'll wrap our prices objects in an IIFE and make the data only accessible to the getPrice store method. The getPrice method can then access the prices object using the bracket notation to retrieve the corresponding price. This turns out to be a nice solution to the problem, and we don't have to worry about missing break statements. Before we move on, here is one last solution to the previous problem. Instead of using the switch statement or an object to store our values, why don't we let each fruit handle its own price inside of a function. Here we define a common prices object and then define a bunch of functions off that object that all know how to get their own price. The apple function knows that it's $1.25, and it will multiply itself by however many items are needed. There are several benefits of this technique. One, if you want to add another fruit, you don't have to modify existing code, all you have to do is add a new method. Two, each method controls its own behavior. For example, the passionfruit code has logic that its prices vary depending on what time of year it is. And three, you don't have to worry about those pesky break statements like you do with a switch statement.
Tumble Through Bug: Demo
Strictly Stray Bug
Parsing Parenthesis Bug
Evil Eval Bug
Evil Eval Bug: Demo
So what we have here is a jsFiddle with the evil eval bug code inside of it, and we're going to go up to this URL, which you're welcome to join me, and we're going to append show, which will show us only the result pane, the bottom right pane, which will be blank, so we'll want to open up our dev tools, look at the Sources tab, take a look at our code, and press Escape which will bring up the mini-console. And now we're going to take a look at this in a little more detail. So here we have an IIFE, we have a function that's immediately invoked at the bottom, we're returning the things that we want to be publicly exposed, and so in this case we want an open method. Anything left is private, so our combinations object here has some private information of the safes and their combinations. So the main safe has a combination of 12345, and the fire safe has a combination of 67890. So what we'll want to do is grab this safe, which is returned from the IIFE, and call open. We'll pass in the safe that we want to open, which is main, and a password that we want to try to open it with. So main will be passed as type, so it'll be combinations.main, which will be evaluated, which we'll come in here to our combinations object, look into main, and give us 12345 as the password. That will be set back to the combination variable and compared to the attempt that we passed in. And if it's a match, then we're going to say the safe is opened, and if they're not a match, we'll say it's incorrect. So if we come in here and say safe.open, pass in main, and then 12345, then we have opened our safe. If we do that again and type in something that's wrong, it'll say it's incorrect. And again we could go and open up our other safe, 67890, and call it the fire safe, and sure enough, we open that, and if we had something bogus then that's incorrect. So at surface value it seems like everything is behaving just like we want. So let's come in here and do something a little sneaky. We will come in here and think like a hacker. So let's say we don't know what safes are there or what combinations, so we're just going to make something up. We'll say makeup. So makeup would go in as combinations.makeup, which doesn't exist and we'd get undefined, and that wouldn't really help us any. But what if we put a semicolon in? That essentially means we're done with our statement, and then we could start writing other code. So let's say console.log, and let's say we knew a little bit about the code, and we knew there was a combinations in there somewhere, which is the private information that we shouldn't have access to. Now it doesn't really matter what password we're going to pick because it just doesn't really matter at all, so we'll put something bogus in here. But if we enter, now we didn't get in, we didn't get the correct information, but we did get all the private stuff. So now we know what all the safes are and we know what all the combinations are. So then we could come back in and put in an appropriate combination, and then we get in. But let's say we didn't know that there was some private information called combinations, we could try something else. So let's go in here and let's say we did know there was a safe called main, but let's hack into it, let's force our way into it. So what we're going to do is instead of just passing main, which would resolve combinations.main, and that returns a value, let's actually treat this as an assignment. So what we're going to say is main=, and then we'll make up some value, 123. And what that will do is when it comes back in here it will say combinations.main= 123, and so it's doing an assignment. So that's a little tricky. So now that we've just reassigned the combination for the main safe, and since we did that when we pass in our combination we can match it up to whatever we just set it to, and voila, we just hacked our way into our safe. Now obviously this is pretty trivial and contrived, but let's go ahead and fix this so that we don't have the same problems. So we'll go back over here, take off show, and it's actually really easy to do. And I've made this mistake before where I used eval and was like oh, well I want to be dynamic and do all this fancy stuff. As it turned out I didn't have to do that. So all we really want to do is we want to grab something off of combinations. And so what we could do is use the bracket notation, and it does exactly what we want it to do. So there's several ways to access a property off of an object. One, we could say combinations.main using the dot notation. That works just fine, and that's the way probably we're used if we're used to C# and Java. But we could also access it using the bracket notation, so I could say combinations, open bracket, main as the string, and close bracket. So what we're going to do is we're going to use that idea, but do it a little more dynamically. We're going to pass in the type, use the square brackets, and that will get us the value. And so this will only give us values within this object, it's not just going to run arbitrary code, which is nice because that's not what we want. So we're going to update this, and we'll go to show, open up our console again, sure enough it opened it. Let's try one of our hacks where we're trying to force our way in. Well, we couldn't get in there. And let's try our console.log. No. So now I can't sneak my way in and run arbitrary code anymore. So anyway, I hope this helped to show you a little bit why eval can be dangerous. It's mostly dangerous if you're evaling code that a user inputs or an API evaluates. If as a developer in your code you have control over what you're evaling, there are use cases for that, but usually if you see eval you need to think long and hard, do I really need this, and maybe even ask someone that you trust and respect to see if maybe there's a better way to do it.
Fickle Figure Bug
For this fickle figure bug, we have some code that will wait for the DOM to be ready, and then we have a little jQuery to initialize our input fields with a jQuery UI datepicker. Can you spot a bug? (Pausing to spot bug) We have to go all the way back to IE7 to see the error in this one. IE7 complains about the trailing comma for our last key value pair in the object literal. This is not a problem with newer browsers, so this might not mean much to you, but for all the other developers who have to support IE6 and IE7, you need to think about this. So why does this even happen? Well, it's a very common thing to try out different options in a jQuery plugin. For example, I might want to quickly see what this widget looks like with the number of months turned on and off, but as soon as I comment out the last property, I get into the same issue that I had before in that now I have a trailing comma on the showWeek: true. Sure I could go and fix this, but often times it's forgotten. Some developers have gotten to the point where they've adopted the comma-first technique to counter this issue, so they could quickly see which commas have been provided. Whatever you do, it's important to know what's acceptable across various browser versions. In this case we care about Internet Explorer 7, 8, and 9. The issue here is that trailing commas both in object literals and also in arrays are errors in IE7, and that's why our previous code was broken. If we move to IE8, then things get a little bit better and neither of these cases are errors, but the array will have one more entry than you probably thought because of the extra comma. You might think that it only should have three items, but it really has four. IE8 added an extra entry with a value of undefined because of the extra comma. Thankfully ECMAScript 5 has made trailing commas legal in both cases, and no longer we get strange behavior with the array, so we should only get the items we meant to include. So with trailing commas, you're safe in IE9 and above. The fix to this bug is really easy, all you have to do is remove the trailing comma on the last property, that is if you care about IE7, which you may not need to on your project. Thankfully JSHint can help you out here as well if you have the ES 3 option turned on, and it will mention that you have an extra comma and that it breaks in older versions of IE. One more important thing to note before moving on, even if you don't care about trailing commas. Let's say for example, you only have to support IE8 and above, you will still need to be careful about trailing commas in your JSON. If you have a library generating your JSON, then you probably should be fine. However, if you're manually building your JSON in code or if you've hardcoded JSON anywhere in your code, then you might want to double-check to make sure you don't have any trailing commas after the last key value pair, because that's going to break JSON.parse.
So that's it for this Statements module. We had talked about being intentional with your semicolon placement, whether you choose to add semicolons or not, there are rules for you to follow one way or the other. My personal preference is to add semicolons as the specification says, and not to rely on ASI. If you want to use the new ES 5 methods that are available, then more power to you, but you must keep in mind cross-browser support. You could provide a polyfill for older browsers, or instead use a shim like Underscore or Lo-Dash. Be careful when using the switch statement, forgetting to add appropriate break statements is a common bug. Make sure to add the falls through comment if that's what you intend, or think about some of the other solutions we talked about as an alternative approach. Be careful when using strict mode. It's highly encouraged that you use it, but make sure you apply it to a function and not the whole file. If you are using IIFEs, then consider wrapping them in parens. In some cases they're needed, or something like them, and in other cases they're just for clarity to the developer. The eval function can be dangerous, so beware. Oftentimes there's a better way to solve the problem other than using eval. If you aren't sure, just ask a developer that you trust. And IE7 and IE8 don't like trailing commas with object literals and arrays. There are some gotchas there, so be careful.
Expression and Operator Bugs
Crude Computation Bug
Mistaken Mold Bug
For the mistaken mold bug, we have a function called getResource that once the resource has been retrieved via AJAX, will invoke the callback function or array of functions that was provided. At the bottom we have two functions, cb1 and cb2, that we'll be using as our callback functions. And then we call getResource twice, both times to get a data.json resource. The first call to getResource we want cb1 to be invoked when the response is available. In the second call to getResource we want both cb1 and cb2 to be invoked when the response is available. Do you know what will be logged in the console? Can you spot the bug? (Pausing to spot bug) So this bug might have been hard to spot unless you know the type of operator pretty well. What we end up getting is a successful response when calling getResource with the function as the callback, but we end up getting the following exception when trying to pass an array of callbacks, Uncaught TypeError: object is not a function. The reason for the error is that the type of an array is not the string array. And what is it you ask? Well let's find out. Typeof is a great operator and very helpful, but in certain cases it doesn't yield the result that you would like. For example, on the left it does a great job with boolean, number, string, function, undefined, and object, but on the right typeof isn't helpful at all, it returns object for null, error, arrays, dates, and regular expressions. Thankfully there are some methods that could help us out a little bit. For example, if you're already using jQuery, there's a type utility method that brings some sanity back to its results. So for example, on the previous page that returned object, now we can return null, error, array, date, and regex as we probably expected. If you aren't using jQuery, or if you already have Underscore or Lo-Dash, then you could also use some of these helpful methods: isNull, isArray, isDate, and isRegEx. However, there's not a method to test for an error object. In addition, Underscore also has some other helpful methods, such as to check for an empty object if an object is the argument's implicit parameter, if a number is finite, and to test for not a number. So we can easily fix our broken code by using one of those helper methods. In this case we'll use the _.isArray method to check if the parameter is an array or not, instead of using typeof. And now we get the output we're looking for, yay.
Mistaken Mold Bug: Demo
Twisted Truth Bug
Twisted Truth Bug: Demo
Crafty Convert Bug
Crafty Convert Bug: Demo
Alright, so here we have the crafty convert bug, you can follow along at the jsFiddle above, but what we have here is a bacon object with a slices property and a buy method. We're going to use a little trick here that we're going to use the console.group, we'll give it a name, and then we'll give it the arguments that we're dealing with. And at the very end of our method we'll call groupEnd, passing the same name and arguments. So what that gives us is something kind of nice. If we look over here in our console we're just using Firebug Lite, it'll actually group our messages that are pertinent for this particular method. Otherwise, there'd just be a whole bunch of log messages and they'd run into each other and it's hard to differentiate where one begins and the other ends. So we'll just be using that nice trick. So essentially we have bacon and we want to buy it, and we want to keep track of how many items that we have. Our buy function you pass in the quantity that you want to buy, and then you pass it if you want to cover it with chocolate or not. The very first one we pass in 0, so we don't want to buy any bacon. It comes in here, and if it is 0, it says WAT? So if we look over here we'll see a message saying why did you even try to buy bacon if you're not going to? So it's kind of a silly thing to do. But eventually we're not covering it with chocolate, we're incrementing 0, which doesn't do anything, but eventually we're saying 0 slices of bacon were purchased, so 0 total slices of bacon. The second one's a little more interesting, we're actually buying something, 5. Since it's not 0 we're not going to get questioned like what am I doing, and we're not doing chocolate, so that's fine, we're just going to increment our slices and then we're going to print out that there's 5 total slices of bacon. And sure enough, we get one message, 5 total slices of bacon! The next one's a little more interesting. We're saying we want more bacon and we want it covered with chocolate. We come in here, quantity is not 0, so we won't see that message, but now chocolate is true, so we're going to add some joy. We're going to increment our slices so we should now be up to 15, 15 total slices of bacon! And sure enough, we're Adding Joy because there's chocolate, and there's 15 total slices of bacon! Now things start to get a little weird. We pass an empty string for our quantity, and a string with a 1 in it for our chocolate. If we look over here in our console, we're getting actually a lot of things in here, which is kind of confusing. It makes sense that it says 15 total slices of bacon because we didn't really add any, so it stays the same, but the other ones, why did those even show up? Well part of the reason behind here is there's the double equals, and what that does is if the types aren't the same on either side of the double equals, it will try to coerce and convert each side to kind of be the same, and then it does a comparison. So what happens here, we're passing an empty string, we're comparing it to a number. When you compare a string and a number, the string gets converted to a number. So what happens here is the empty string gets converted to a 0, which is equal to a 0. And so that's why we actually get into this if statement, and it says WAT? So then we'll have to look at the next item here. We have a string with a 1 in it and we compare that with a Boolean. So if you're comparing a Boolean to anything else, what happens is the Boolean gets converted to a number. So true gets converted to a 1. So now we have a number and a string. So the string gets converted to a number, and if you have a string, as long as it's actually a valid number inside of it, it'll get pulled out and converted to a number. So in this case we have a 1 equal to a 1, which is true, and now we are able to say console.log Adding Joy. So it's confusing, yes, there's a lot of conversions going on, but since we actually said double equals, that's what we get. If we come down further to our next example, we are passing in exclamation point for the quantity, and we're actually passing in object for the chocolate. So let's talk through this one. So we're passing in an exclamation point, eventually it'll say Adding Joy, and then we'll get this weird message, 15! total slices of bacon! So we'll come in here, quantity is an exclamation point, so what happens is that's a number and a string, so the number stays the same and the string gets converted to a number. Of course what's in this string is no way converted to a number, so that gets converted to not a number, which is not equal to 0, so that doesn't get in there, whereas the object comes in here as comparing against a Boolean, so what happens there is Boolean gets converted to a number, which is 1, and then chocolate gets passed through something called toPrimitive. And the way toPrimitive works is it will first call valueOf to try to abstract a value that's a primitive. Well, in this case it can't get anything. So the second one it goes to is it will call toString and see if it could get a primitive out of that. And we did actually provide a toString, so it will return a string of 1. And so now we have the number 1 compared to a string with 1, and so then the string will get converted to a number, and since there's a number inside the string, that's a valid number, it will get converted to a 1. So now we have a 1 equals to 1, which is why we're Adding Joy. A lot of weird stuff, but it's because we're using the double equals. We can make this a little less confusing by using the triple equals, which does not coerce types on each side. If they're different types, then it's false. So if we rerun this it will be a little bit better, it won't be perfect yet. So the first three ones we're fine with. It's the last two that we don't really want to do anything. We're fine with the, this buy one's actually fine, but it would be nice if it just didn't do anything. And this last one's a little confusing. What it does here is when we use the addition operator, if one of the items happens to be a string, then the number will be converted to a string as well, and so they'll concatenate and not actually add, and so that's why we get a 15!, those are actually strings being concatenated together. So let's go in here and double check that the quantity is a number. Quantity, and if it is a number then we want to continue, (Typing) and if it's not, then we'll just, we'll do a little formatting, if it's not then we'll just not run all that code, we'll go ahead and end our group, but that's it. So let's run this again. So here we go, we have the first three run just fine, but the last two we don't actually console.log anything, so they're just kind of no ops. So hopefully that makes a little more sense of some of the dangers of the double equals. Now again, you could memorize all these rules, and that's fine, and it's actually in a weird way kind of fun to know what's going on, but most of the best practices these days will encourage you to use the triple equals instead. Now you have some people who think it's a little overzealous to always say triple equals. So for example, if I knew this was a number and I came in here, and since 0 is obviously a number, and at this point I know quantity is a number because I just tested it, well it would be technically safe to use double equals to test this number against this number because they're the same type. And as we looked before, even when you use the double equals, if they're the same type, it obeys all the rules as if it were using the triple equals, so you're not having any danger here. Now however, chocolate, we don't really know what type it is. We're not checking it and we're testing it as a Boolean, so it might be a little dangerous to use the double equals, so it's better to use the triple in this case, unless we actually knew it was Boolean. So these are some gotchas, hopefully that makes a little more sense, and there you go.
Problematic Pause Bug
In this problematic pause bug, we have a max function that accepts n number of arguments, and it will loop over them and return the largest number that it found. Take a few seconds and see if you could figure out what will be logged to the console. Can you spot the bug in this piece of code? (Pausing to spot bug) So there may be several things I'm doing in this code snippet that you might not be familiar with, but we'll unpack that here in a few minutes. First let's check out what the output of this code is, and of course, we have a bug because we always do, right? Once the 1 is processed, it is identified as the max, then 3 comes along, which is the largest, and so forth, until hopefully we get a max of 9. But wait a minute, max's console.log is undefined, how can that be? Well let's take a look at the comma operator, which I was using in several places in the previous code snippet. The comma operator evaluates both sides of its operand, from left to right, and returns the value of the second. So the following piece of code evaluates single to 3, then evaluates double to 6, and then it returns 6, and assigns it to the wat variable. It's a pretty easy concept to follow, but it's important to know. So the main issue with the buggy code is that I had a comma after max and it was returning the arg variable from the max function since it was on the right of the comma operator. So if I remove the arg from the return statement, things start to work as expected. I'm still using the comma operator to store the length of the arguments when initializing the i variable, and in addition to checking if i is less than length, I'm also assigning the arguments at index I to the arg variable, which cleans up the code inside the for statement just a little bit. I removed the console.logs, but if you recall those were using the comma operator as well, so I could sneak in an extra statement where it didn't really belong. As a side note, you probably want to be careful with the comma operator, as it encourages you to write really terse and hard to read code. But if it makes sense or really cleans things up, then I think it's okay. As for most things, try to follow best practices unless you have a good reason. Use your best judgment and ask a friend too.
Ignored Invention Bug
In this ignored invention bug, we have a Cat constructor and we're creating two new cats, Fluffy and Midnight, and then we're logging them to the console via JSON.stringify. Can you spot the bug? Do you know what's really happening? (Pausing to spot bug) So Fluffy ends up logging to the console correctly, but Midnight logs out undefined, hmmm, that's unfortunate. But thankfully Midnight hasn't been lost completely, he could be found on the global window object. However, that's actually not cool at all. So what's going on exactly? Well, we forgot to include the new operator when calling the constructor to create Midnight. What does the new operator even do? Well, it creates the new object, sets its prototype to the constructors prototype, executes the constructor using the new object as the this context, and then returns the new object. So let's take a look at the following code and talk through what's happening. If we use the new operator along with the constructor, a new object will be created. Once we get inside the constructor, the this context will refer to the newly created object. However, if we tried to call our constructor without using the new operator, then no new object will be created, and then when we get inside the constructor, the this context will refer to the global object, which is the window object. This is bad because we're now appending things onto the window object that is global to everyone. Oh boy, as a result it is considered a best practice to uppercase your constructor function to communicate to other developers that something special needs to be done with this function. It's a constructor and it needs to be new'd up. If you're concerned about developers accidently calling your constructor without using the new operator, then you could add some extra code to help protect against that. Here in our constructor, we're checking if this is an instance of a person. If it isn't, that means it wasn't new'd up correctly, so we could manually new up a version of person, passing in the appropriate arguments, and that will make sure the this is a new person and not the window object. So in order to fix our code, all we needed to do is make sure we use new operator before creating our Midnight Cat, and all is well. And now we don't have any leaked items on our global window object. In addition, we added some code to our constructor to protect against someone not using new, just in case. And again, we have JSHint to the rescue, and it would've given us the following error in our previous buggy code, Missing new prefix when invoking a constructor.
Ignored Invention Bug: Demo
So what we have here is our ignored invention bug, we're working in a jsFiddle, and you're welcome to follow along at the URL above. Here on the right we're using Firebug Lite just to look at our console, and in our left is our code. We have a Cat constructor with name, breed, and color, and we're creating new instances of Fluffy and Midnight, and then we're going to log them out, and we're also going to log out the window because there happens to be something going wrong here and we want to see it. So here we're newing up fluffy, Fluffy, Ragamuffin, White. If we look in our console, sure enough, here's Fluffy. And then we're newing up midnight, Midnight, Bombay, Black. But when we console.log it it's undefined, so where did it go? Well if you look closely we actually didn't put the word new here in front of the cat. So what happens, it actually didn't create a new object, but it still went in to the constructor, but what was this? This was the global object, which is the window. So what was really happening is it was appending name, breed, and color off of the window object. So if we come down here in console.log, window.name, window.breed, window.color, and look in our console, then it shows up. So there's a couple ways we could fix this. One is just to actually provide the new keyword right here and then update our code, and sure enough, things work just fine, now we have both objects. But since someone forgot to put new, maybe they would forget later, so let's take a look at a different technique that we could use. We'll come up here and inside of our constructor the first thing that we'll do is we'll double check that whatever this is is an instanceof the Cat that we want. And if it's not, if it's not an instanceof the Cat, then what we'll want to do is we'll want to return a new Cat and we'll pass the name, breed, and color. So since we are returning, it will never actually get to this portion of code, but the fact that it's not a Cat means that it wasn't actually new'd up correctly, that this would be the window, and so we'll actually want to say oh, well we accidentally came here through the window, let's actually kick off the process again, but this time let's new up the Cat. So even though I'm not saying new here, what will happen if we update this code, is it will still work, which is great. And so we've kind of protected ourselves against people who don't say new. Now again, it still works if we say new, either way it will work just fine, but that's a nice way to protect ourselves.
Inaccurate Increase Bug
In this inaccurate increase bug, we have a fruit array of strings and we're incrementing the index and the count to add two new items, orange and banana, and at the end we console.log the contents of the array. The desired output is listed above in the comment, apple-1, orange-2, and banana-3. Do you know what the output will be and can you spot the bug? (Pausing to spot bug) So unfortunately we didn't get the desired output, but you knew that we had a bug, so that was obvious. What we do get as output is orange-2 and banana-3, and that's it. So what happened to apple-1? Where did it go? So the reason things aren't working as expected is because we're using a combination of prefix and postfix operators, and we're also using them within a complex statement. This combination can lead to some confusing bugs. The difference between prefix and postfix is easy to understand conceptually, but in practice it could be easy to get wrong. Plus plus x returns the operand after adding 1, whereas x plus plus returns the operand as is and adds 1 after that. If these are on one line by themselves, it isn't too hard to understand, but once you start mixing them into a complex statement, all bets are off. For example, let's take a look at this code. We have a new array with y = 0. We concat the test string to ++y and assign it to our array. After that statement, the string is at index 0 and the value of y is 1. If we repeat this statement slightly, but used a postfix instead, then we get a result that we probably didn't intend, an array with test1 and test1. To fix our problem, we could split out the code to increment our variables onto their own line. Yes, it is more cumbersome, but the outcome is much more straight forward for developers to understand, and the chances of accidentally introducing an error is decreased. JSHint also helps us out here and lets us know that we're using confusing pluses, which should be a head up to us that maybe we should reconsider how we're coding this. Another solution to this particular issue is to use the length of the fruit array to both help insert a new record and also to help concatenate the string being stored. Since the length of the array will always be a value one higher than the last index, we can use it to append new records to our array, or we could also use the push method off the array to insert as well.
Raised Resource Bug
Raised Resource Bug: Demo
Early Execution Bug
Morphed Method Bug
Morphed Method Bug: Demo
Confounding Context Bug
In our confounding context bug, we have a student object with name and resume properties, and a study method. We're saving off the student's study method to a local memorize function, and then we proceed to call this student.study method, log his resume, and then we call the memorize function, and then log the student's resume again. Can you spot the bug? Do you know what will be logged in the console? (Pausing to spot bug) So as it turns out, if we ran this code we'd get something in the console first, John is studying chemistry, which is what we're expecting, but then we'd also get a runtime exception thrown, Uncaught TypeError: Cannot call method push of undefined. Can you spot the bug now? Well the bug comes down to the concept of the this implicit parameter. Remember how we talked about the special arguments parameter? Well this is also a special parameter and contains the context of the function. In the next slide we'll unpack this somewhat. If we have a top level function, hiWindow for example, and then invoke it, the value of the this implicit parameter will be the global object, which is the window object. If we have an object with a method, for example this person object with a greet method, once we call the greet method off the person object, the this implicit parameter will be the person, the object that invoked the method. However, if we saved off a method to a variable, for example, saved off person's greet method to a hello variable, if we invoke the hello function, the this implicit parameter is no longer the person object, but it defaults to the global object as our first example showed, and it will be the window object. At first glance that kind of stinks, but there are some ways we can manipulate the this implicit parameter to be what we want. We could, for example, use the call method off the function to change the value of the this implicit parameter. In this case we're making sure that the this context of the hiWindow function will contain the name of John, which is what we see here in the console log. Instead of using the call method off the function, we could have also used the apply method. They both let you invoke a function and control its this value, the main difference between the two is how you pass parameters. The next piece is going to show the bind method, which is yet another way to control the value of this. As in our last slide, we have a person object with a greet method. We could use the bind method off of greet to specify a context that will be used as the this parameter. Bind will return a new function that is ready be invoked and we'll keep the this implicit parameter to whatever you set it up to be, instead of being the global object like we saw in the last slide. So in this case we're binding person.greet to an object with the name of Jake. That way whenever we invoke the hello function, it will remember Jake as its this context instead of something else. And finally, we could have a constructor function, like we have a person here. The constructor function is meant to be new'd up, and inside the constructor the this implicit parameter is a new object that will be returned. So in this case we're creating a new person object, setting its name to Jane, retuning that object, and then calling the greet method, which will console.log its name property. So as a review, here's a chart showing what the this implicit parameter will be in various use cases. If you were to just type this in the console, or top level scope, you'd get the global object, which is the window in the browser. If you call a function that isn't off an object, then the this context will be the window. If you call a method off of an object, then the this context will be that object itself. If you invoke a function using the call method, then you can provide the this context as the first argument. If you want to pass parameters to the actual function, then you provide those as additional arguments to the call method as shown here. In the same way, you can do the same things with the apply method. The only difference here is that if you want to pass parameters to the function, you put them all in an array as the second argument to the apply method. ECMAScript 5 introduced the bind method, which allows you to wire up a context that will be used whenever a function will be invoked. Bind returns a new function that remembers the context you bound so that when it's invoked, the this context will be what you told it previously. And finally, if you have a constructor function, the this context inside the constructor will be the new object that was created and will be returned from the constructor once it's finished. So in order to fix our previous code, we'll use the call method off the memorize function and set the context to the student. That way, once it's invoked, the this implicit parameter will be the student and everything will just work as expected. We could've also just called the apply method instead. Or, when we assign student.study to memorize, we could have used the bind method at that point. Another change made is to store off the this context as the that variable, so we could use that inside of the addToResume function. This is yet another way you'll see some developers get around the issue of controlling context. There are lots of ways to solve this issue, the main point is just to understand what options are available and what's really going on. It turns out having our code in strict mode could have saved us in our previous broken code example. Strict mode eliminates the coercion of this to the global object. Without strict mode, invoking the hiWindow function or trying to call the greet method with undefined would coerce the this context to the global object, the window. But if we add strict mode, then both cases would not coerce to the window. The this context in the hiWindow function would be undefined, and the context in the greet is null since that's what we set it to. Without strict mode, undefined or null would get coerced to the window. Thankfully JSHint can help us out a little bit if we are in strict mode. Our previous buggy code example would have had the following JSHint error, Possible strict violation. In addition, our code would probably break since the object was not coerced.
Confounding Context Bug: Demo
So here we have the confounding context bug. We're using jsFiddle and you're welcome to follow along at the above URL. We have the dev tools open at the bottom, and we have our code here in the middle. What we have is a student object with name and resume properties and a study method. We're saving off the study method to a memorize function, and then what we're going to do is call student.study, saying that he's studying chemistry, then we'll print out the resume of that student, and then they'll memorize history, which is essentially just studying it, and then we'll print out his resume again. But what we find if we look in the console is things partially work, but not so much. We get a console log message that John Smith is studying chemistry, but then we get an exception, so let's take a look. Here we're calling student.study chemistry. We come into the study method, and obviously this console worked just fine, but then what happens, we have an inner function and then we were invoking that function. So we're passing in the subject, we're getting into the inner function. So what's happening is there is no resume, and so we're trying to call push, but there is no push, and so it blows up. So why is there no resume? It's because the this in here is specific to this add resume, it's actually the window object, and it's not the this of the study. So that's a problem. So one way people get around that is they will create a new variable, and a lot of times they'll call it that, and they'll save this off to it, and in here they will change this to that. And so now, essentially we've made it so that variable is the this from the study and not the this for this particular function. It's a little weird, but let's run the code. It'll work a little bit better. So now we have John Smith is studying chemistry, we could print out, sure enough, our internal resume has chemistry, but now we have a problem with our memorize function. We have result is studying history, well that's kind of weird because where did result come from? So let's look in here, memorize history. We'll come in here, the subject is history, and somehow this .name is result, which is really kind of weird. If we come down here to our dev tools, we could switch to the Result pane, which is this window, and we could actually look that window.name is result. It's actually looking at the name property off the window object. So when we call a function that's not off of an object, by default the this becomes the window, which is not what we want. So one way to handle this is to invoke the call method, which allows us to choose what the this implicit parameter to be when it's invoked. And what we're going to choose is we want it to be the student. So we want to invoke memorize, but inside of it we want the this to be the student, and then we're going to pass history as our parameter. So now everything works just as expected. John Smith is studying chemistry, his resume is chemistry, now John Smith is studying history, and now his resume has chemistry and history. Another way we could have changed this is to use the apply method instead. It also lets you choose what the this implicit parameter will be as the first argument, but if we want to pass arguments to the function, we actually have to put them in an array as our second argument. We'll run this and everything still works. Another way we could have solved this is used the bind method, which is an ECMAScript 5 method. Now what you do here is we call bind and then we tell it what we want to bind it to, so we want to bind it to the student. So that's what the this implicit parameter will be. It will return a new function that will remember what the this implicit parameter should be, because we bound it to the student. So now if we come back here we could revert this back to what we had before, and even though we're just calling memorize right here, instead of the this being the window, it will be the student because that's what we bound it to. So if I run this then everything again will work just fine. If we wanted to, we could actually get rid of the that this technique and instead use one of the other techniques that we just learned. So we could use call here. And what we'll do here is we'll say we want this, the this of the study, to be the this when it actually invokes the addToResume function. So it will come in here and this will actually be the this of the study and not the this of the function. So if we run this then everything still works just fine. So there are lots of ways you could actually manipulate what the this implicit parameter will be using call, apply, and bind, or using the that this technique. The main take-away is to know the various different techniques and how to use them to change the this implicit parameter.
Escaped Environment Bug
For the escaped environment bug, we have selected an unordered list element from the DOM, and we have a loop creating 10 list items, setting their innerHTML, adding a click event handler, and appending them to our list. Can you find a possible bug in this code? (Pausing to spot bug) This bug's a little tricky to spot unless you actually run the code. Here's a simplistic animation to simulate what's happening. If we come over here to Link 1 and click it, the click event handler will be invoked and it will console.log the index that was clicked. But wait a minute, it console logged that I clicked the tenth index. That's not right. It should have said index 1. If we move down to Link 4 and click, we'll see the same console log message. Hmm, that's not right. As it turns out, if we click on any of the other items, they all console log the same message, You've clicked 10. Do you know why? Well, although we're adding event handlers dynamically, the message that's displayed is created at a later point in time when the click event occurs. The value of the variable i will not be the same as it was when the event handler was wired up, it'll actually be whatever value i was after the loop was completed, which is 10. What we need is somehow to make the event handler remember the value of i at the point when we added it, which brings us to our next point. Closures, we need them. The Mozilla Developer Network defines a closure as a special kind of object that combines two things, a function and the environment in which that function was created. So in other words, a closure is a function in some special memory that you could access at a later point in time. Here's a simple example of a closure that MDN shows to explain this concept. We have a makeAdder function statement and its job is to make adding machines. Before we unpack how it works, let's first take a look at how we're going to use it. Down here we use the makeAdder and say, hey, make me an adding machine that knows how to add the number 5 to whatever I give it. So, makeAdder will create an adding machine that remembers the number 5, and will pass it back to you and will store it in the add5 variable. In the same way, we'll ask makeAdder to make another machine that knows about the number 10, and it will return a special new adding machine and will store it in the add10 variable. Once you have your adding machine, you can invoke them and pass a number you want to add to them. For example, if I pass 2 to the add5 machine, I'd get 7, or if I pass 2 to the add10 machine, I'd get 12. The reason that adding machines work is that they were able to create a closure around the initial value when it was created. So for example, when I call makeAdder with 5 as the argument, it gets mapped to the x variable, and then a function is returned, which will be our adding machine, and it accepts y as a parameter, which will be added to the initial x value of 5. But how does it still know the value x if the function was returned? Exactly, that function is enclosed around the variable x so when it needs it it can look it up in its special memory environment. Yeah, I know it's a little heady. It took me several times before I really grasped the concept. What I found is even if the theory doesn't make sense, the important part is to remember the behavior that we saw where it wasn't remembering the correct data. If you see that behavior, then try to remember, hmmm, maybe I need a closure, and then go look it up. So let's go ahead and apply this closure concept to our problem. The problematic code was the event handler part, so what we'll do is add a closure to the event handler to remember the index of the for loop so that when a log message is made, it can use the right value. Do to this, it looks a little weird, but we're going to have a function, and inside of it return a function that will log our message. Our adder function will accept an index parameter and will pass in the for loop's i variable as an argument. The inner function will be the actual event handler that is a closure around the index value, and when the user clicks on one of the list items, now it will show the appropriate closed over value, you've clicked on 1, you've clicked on 2, etc. As an interesting side note, JSHint will actually complain about this code saying that we shouldn't make functions inside of a loop. It actually would have told us this with a broken code as well, so let's refactor this just a little bit on the next slide. Not only are we going to refactor this just a little bit because of what JSHint says, but also it might make the concept a little bit cleaner and easier to understand, since the code won't look as weird. So what we'll do is we'll move out the function that returns the function into its own function statement below, and we'll call it clickHandler. Then we'll use the clickHandler in our loop, passing in the index. See, doesn't it look a little bit cleaner? The code works just the same, but we split out the function that creates the closure.
Escaped Environment Bug: Demo
So here we have the escaped environment bug, you can follow along at the jsFiddle URL above. We have an unordered list and here we're grabbing an instance of that element, and then we have a for loop going over 10 times. Each iteration in the loop we're creating a new list item, we're changing its innerHTML based on the indexed, and then we're adding some behavior. Here we're adding a click event handler. When you click on an item we want to actually say you've clicked on 1, or 2, or 3, or whatever the index was at that point in time. And then at the end we append the list item to our unordered list. And as you can see over here on the right, sure enough, it did create all these items and appended to the DOM, which is great. So if we come to click on one of these, we'll click on Link 2, and then Link 6, and 9. You'll see in the console it's actually giving us the same message every time, You've clicked 10, You've clicked 10, You've clicked 10, which obviously is not correct. This is the case because the console log, the code inside the callback, isn't invoked until later when I actually click the item. And at that point in time, i is set to 10 because i, once it got outside of the for loop, was set to 10. So every time I click on one, after that point in time, they'll always be 10. So what we really want is some way for this function to remember the i that was set at that point in time when it was bound, and not at the end after everything was done. So what we're going to do is create a closure, and the way we're going to do that is to have a function inside of a function. And we're going to return this one. So what we're going to do is we're going to have a parameter here, index, and we'll use that right here, and then we'll pass in an argument of i. And we're going to go ahead and put one extra level of parens around here, it's not necessary, but it helps communicate to other developers that hey, something special's going on here. So what happens is we pass in i, which is the index at that point in time, it will get passed in as the index, and then we're going to return a new function, this highlighted portion, that we actually want to be invoked when someone actually clicks on the item. So if we click on 2 for example, all 2 knows about is this function that's highlighted. And inside the function it's referring to index, but you notice that the highlighted code doesn't know anything about index whatsoever, so where does that come from? Well it comes from that closure. So a closure is a special function, the highlighted piece of code here, with some special memory, and that memory is what was created at the point in time when it was returned, and so it has some special memory that knows about index, even thought the highlighted code doesn't show index being passed in, it knows about that value, and so it can actually pull it from that special memory. So now if we come in and run our code, let's clear our console, and we start clicking, we'll actually get the appropriate indexes, which is great, because now the function that's being invoked remembers that number when it was created because it was enclosed over. So if we run JSHint we'll actually get an error that it doesn't like that we're making new functions inside of a loop. So what we're going to do is we're going to pull this piece out, right here, into its own function, we'll call it clickHandler. And so what we'll do here when we wire this up, it will look a lot, lot cleaner, is we'll say clickHandler, and we still have to pass in the index because that's what we want it to remember, but things look a little bit cleaner and all the confusing looking code is still in here, we still have a function that's returning a function because we want to create that closure, we want this function to remember the index so that it could actually pull from that special memory. But if I run this again and clear my console, we'll still get code that works appropriately and gives us the correct index. And still if this doesn't make total sense, the key point to remember is the behavior that we're seeing. So before we had code that couldn't remember a specific value, it kept giving us the same value over and over again. If you get into a situation like that in your code, it very well could be that a closure could help you, and so at that point in time you could just say, well let me look that up on the internet again and try to learn that concept. But it's the behavior you want to try to remember, and then hopefully use a closure from that point on.
Peculiar Parameter Bug
In our peculiar parameter bug, we have the function sum and average. The sum function takes n number of arguments and then will iterate over the numbers, adding them together, and returning the value. The average function uses the apply method to dynamically pass all its arguments to the sum function, and then divides by the number of arguments to return the average. Can you spot the bug after calling the sum and average function calls below? (Pausing to spot bug) Phew, did you find it? You may have thought there was an issue with the average method and how it was calling apply, but nope, the issue is with the forEach in the sum function. Let's assume for a minute that we're in a modern browser that has ECMAScript 5 support, there's still an issue. The problem is that the argument's implicit parameter is not really an array, so there's no forEach method off of it. Oops. Yup, arguments is not an array but it is an array-like object. Umm, what does that even mean? Well, arguments does have a length property describing how many items were passed to the function, and you can use the bracket notation to access each individual argument in the not so array. However, the buck stops there, there are no other array-like features beyond that. You can't call forEach or sort or join, or any of the other array methods. So one way we could fix this is just use a standard for loop and control our own index to iterate over the arguments. That's easy enough to do, and now our code's working just fine, we get 15 and 9.4. If we really did want to use forEach, then there's a nice little trick you could use to easily convert the arguments array-like object into a real array. What you do is invoke the call method off the empty array's slice method and pass arguments as the context. And now you'll have an official array to deal with and you could use the forEach method to your heart's content. And again, the code will work just fine, we get 15 and 9.4.
Condemned Criterion Bug
Value, Variable, and Literal Bugs
Booked Byword Bug
Booked Byword Bug: Demo
Here we have our booked byword bug in jsFiddle, you could follow along at the above URL. Here we have our code, we have a collection object, which is the result in an IIFE, we have add, get, and delete as our public methods, and we have a private items. What we're doing is we're actually exposing the items, even though it's private, just so that we can console.log and see what's going on. But before we even look at the code, we have an exception here, Unexpected token delete. So we come in here and we're like, oh well, obviously we don't like delete here so let's just name this remove because delete is actually a reserved word. And so we will call that remove, and then we will map delete to remove here, and now we will run it again. And now everything works just fine. Here we're adding some bacon and eggs and cheese to our collection, then we're logging the _items, which is our private information that we've exposed, then we get the 0th index, which should just be bacon, and then we delete the first one at index 1, which is eggs in the middle, and then we log it again and basically we've removed the eggs, so everything's great. But unfortunately, if we run this in IE8, we will blow up. So let's update this. Just to verify that let's update this, we'll copy this URL, we'll come over to BrowserStack, we'll paste in our URL, say show, and then we'll run it against IE8. We'll start our testing and it will kick up a VM and it will point to our URL that we want, which is jsFiddle, and then we should see an error, because IE8 runs ECMAScript 3, not ECMAScript 5. And sure enough down here there's an error, we'll open it up and show the details, and it's expecting identifier string or a number. And if we actually looked at the line number it would be inside of our return, so let's close this. So it's having a problem with this. There are a couple of ways we could have solved this. One is we could've put quotes around delete because delete is a reserved word. So in ECMAScript 3, reserved words can't be an identifier or identifier name, but in ECMAScript 5 keywords can be identifier names, which is why we're able to have a delete here. But if we want it to work in both, then we'll just put this in quotes, because that's okay, but then when we actually go invoke it we would have to use the bracket syntax and then pass in delete as a string here. Now this will work in both ES 3 and ES 5, so if we update this, copy this URL, go back to BrowserStack, type in our new version, kick it off. (Loading) So what we'll do is we'll open up our dev tools, and then we'll run it again. Let's open up our script, and we'll pull this up and then we'll refresh, and there we go, it works just fine. We have bacon, eggs, and cheese. It logs bacon and then it removed the cheese. Now we had to actually run this with the dev tools open because console doesn't exist with thte dev tools closed. So if we open them up in IE8, then the console logs will work just fine. But it does work, however, that's a little annoying that we have to do that. So to get around it completely we could just avoid using a reserved word at all and we could just call it remove here, or we could call it delete item, or pretty much whatever we wanted to do as long as we stay away from the word delete. And that will continue to work both in ECMAScript 5 browsers and ECMAScript 3 browsers.
Revealing Recall Bug
Revealing Recall Bug: Demo
Relative Realism Bug
Relative Realism Bug: Demo
Tangled Tag Bug
In this tangled tag bug, we have the following code. We're using jquery and jquery-ui. Let's assume we've pulled all the in correctly and we're good to go. We'll run the following script at the bottom of the page so the DOM will be ready at that point. We'll use jQuery to select all the date fields, and then we'll initialize those elements with the jQuery UI Datepicker. Can you spot the bug? Do you know what will happen? Hint, it works just fine in modern browsers, but there's an exception in Internet Explorer 8. (Pausing to spot bug) So again, you might not need to support IE8, but it's still a good thing to know in case you ever need to support it, or help someone else track down a bug in their code. The exception that we see in IE is, Object doesn't support this property or method, which is actually really confusing, so what's really going on here? Well there's something really interesting going on here. There's something called named access on the window object, which is described at this URL in more details, but basically what it says is that names of iframes, frame, and framesets will be exposed onto the window, certain elements with the name attribute will be exposed on the window, such as anchor, form, image, etc., and elements that have an id attribute will be exposed on the window. Wow, talk about cluttering the global namespace. So for this code snippet we have an HTML element with id of hello, and then a script that can set the elements in our HTML with a string. And this works because the browser made the div accessible off the window object. The above code is as if I had typed window.hello.innerHtml = Howdy, it still works and it shows that yes, indeed it is on the window. JSHint will help us out a little bit and tell us that datePicker is not defined, which isn't necessarily telling us about this exception, but it so happens that this is why we're having a problem, at least in some browsers. Let me explain further. So I mentioned that modern browsers don't have this issue and they just work, right? Well, they actually support this named access on window object too. So what's different? Well the difference is that Internet Explorer 8 not only makes them accessible off the window, but if you try to reassign them to something else you get an exception. So that's the difference. Other browsers expose these elements on the window too, but if you decided to reassign them to something else, no exception is thrown. So, this issue is partly with IE8 being weird, but it's a problem because we're creating global variables when it wasn't really necessary. Even if we did declare our datePicker variable, it would still be global in this instance. So what do we do? So to fix our issue we'll just create a simple little IIFE wrapper to keep our memory off the global namespace. That will keep our code from clashing with any named elements on the window. Another way you could have fixed this is just to use jQuery chaining and not introduce a new variable at all. In addition, you could have used the DOM-ready event handler to use as your function wrapper. We really just need something to place our memory in so it wasn't on the global namespace. However, for this simple example, waiting for DOM-ready isn't necessary since our previous slide had the code at the bottom of the page before the closing of the body tag, but I think you get my point. Just be careful of this so-called feature. I actually prefer not to rely on this named elements on the window, for some reason it just doesn't feel right.
Double Define Bug
For this double define bug, we have a person object with some name and address properties and a toString method. At the end we're console logging the results of the toString. Can you spot the bug? (Pausing to spot bug) So the error is, what we get in our output may or may not surprise you. You may have expected the phone number to be 555-123-4567, or you may have thought it would be the value below, which is what is really outputted. The issue is that we define the same key in our object literal twice, doh, and that isn't good and most likely it was a mistake. For silly examples like this it might be trivial to notice, but imagine if you have an object that's much larger, it could be really hard to miss in cases like that. So the main thing to remember is that the last key in object literal or a parameter in a function with the same name wins. So to see this behavior on a smaller scale, let's look at some snippets. Here we have an object literal with key1 listed twice. If we go to console.log myObject.key1, then we'll see the value that was last assigned. In this case key1 will be Goodbye.1. If we take a look at another simple example of a function with multiple parameters, if that happened to have the same name like param1, then whichever parameter was last would get the value. So if I called myFunction with Hello.2 and Goodbye.2, then the end result of logging param1 would be Goodbye.2. Thankfully JSHint will warn us about such things, that we have a duplicate key or a duplicate parameter. If we go one step further and turn on strict mode in ECMAScript 5, then these JSHint errors actually become runtime exceptions, so that's good. So we get an Uncaught SyntaxError: Duplicate data property in object literal not allowed in strict mode, and, down here we get Uncaught SyntaxError: Strict mode function may not have duplicate parameter names. So to fix our code what we'll do is put it in strict mode to give us runtime exceptions if there's a problem, and we'll also go ahead and remove the redundant object key to resolve that problem. And now there shouldn't be a question or confusion as to what the output should be.
Transform Total Bug
Yay! For the transform total bug, we have a purchase function statement that accepts an item and an amount. Inside the function it's parsing the amount, and then converting it to a fixed number in a console.log message. Then at the bottom we go to purchase some eggs for $1.00, and then we found some crazy expensive rare smoked bacon that costs $8.00. Can you spot the bug? (Pausing to spot bug) Well here's the output from our code. At first we got eggs for $1.00, which looks correct, but then we got our bacon for, what, free? That doesn't make any sense, it's supposed to be really expensive but hey, I'll take free too. But as it turns out that this bug is only in Internet Explorer 8, which by now shouldn't really surprise us. However in a modern browser we would've gotten the following results of eggs for $1.00 and bacon for $8.00. Well let's take a step back and look at parseInt, it takes two parameters. The first is a stringToParse, which is what we're passing. But the second parameter is a radix, which is optional, and we were not passing it. Here are the rules that are applied if the radix is not provided, undefined or 0, and the item to parse is a string. If it starts with a 0x, then the radix is 16, if it starts with a 0, then the radix is 8, and if it starts with something else, then the radix is 10. The exception to this rule is if you're using ECMAScript 5. In that case the radix will not default to octal, 8, if the string starts with a 0, which is why our previous example was working in modern browsers that use ECMAScript 5, but not in IE8, which uses ECMAScript 3. So the following examples, 0xA, defaults to base 16 and the value is 10, and 015 defaults to base 8 in ECMAScript 3 and the value is 13, or in ES 5 the base is 10 and the value is 15. Thankfully JSHint will let us know if we're missing the optional radix parameter. We don't want to leave this optional because ES 3 could pick octal when we didn't really mean it, so it's safer to always provide a radix, and most likely you'll say base 10. So in order to fix our buggy code, all we have to do is provide a radix of 10 and everything works as expected, although now we have to pay $8.00 for that really expensive bacon, maybe it was better free after all. Ha, not really.
Transform Total Bug: Demo
So here we have the transform total bug in jsFiddle, you're welcome to follow along at the URL above. We have a purchase function where we want to purchase an item, so eggs for example, and for an amount, so $1.00. We'll come in here and parse the amount, and then we'll console.log a fixed version of the amount. If we come down here, sure enough, we've got eggs for $1.00 and we got some really crazy expensive bacon for $8.00. Now everything's fine here, but if we come over and bring this URL to an old browser, such as IE8, then we'll have a problem. So let's go ahead and kick this up, we'll launch a VM in our browser, we'll have to open up our dev tools in order to see our console log. So let's come in here, we'll come over to the Scripts, and refresh. And what we'll notice is that eggs is $1.00, but our bacon that's supposed to be really expensive is free, it says $0.00, so that's a problem. So why it works in the new browser and not the old browser is that ECMAScript 5 has some different rules than ECMAScript 3. So in the old browser, ECMAScript 3, if a number started with a 0 and you did not provide a radix as the second argument to parseInt, then it would default to base 8, whereas we probably meant base 10. So it's really encouraged that you provide a radix so that the browser doesn't make it up for you. So we were going to say we want it to be 10 of decimal, and so that way it will in modern browsers or in old browsers. Now with ECMAScript 5, the reason it works is even if it starts with a 0, ECMAScript 5 says don't actually default it to base 8, they just removed that rule, so it'll assume 10, but for older browsers it assumes 8 if it starts with a 0. So what we'll do is we'll update this, grab the URL, come back over to our IE8, say show, we'll clean the console, and then we will run this. And sure enough we have $1.00 for eggs and $8.00 for our really expensive bacon.
Amount Aware Bug
So for this amount aware bug we have a similar problem as the last one, but a little bit different. Here our purchase function parses a float, and if the number parsed is not a number then we'll throw an exception, otherwise we'll console.log the item and the price with a fixed-decimal format. Then later we'll call purchase to get some eggs for $1.75, and then we'll buy some priceless bacon, the $8.00 bacon, wet our appetite for something even more exotic. So we found some bacon that's so rare and tasty that no price could describe its value. Can you spot the bug? Do you know what's going to happen? (Pausing to spot bug) You might be surprised by the result, or not. Here we have eggs at $1.75, but we kind of expected bacon to throw an exception, and it did not. Instead it printed out NaN as the price of the bacon, which is silly and it shouldn't be displayed. So what went wrong? Do you know? So this one has an easy fix. It turns out you can't compare not a number to itself using double equals or the triple equals operator. If you tried, you would always get false. So there's a special is not a number function that you need to call instead to test if the value is not a number or not. Thankfully JSHint will catch this and recommend that we use the is not a number function. So thankfully the fix is really easy, we just switch our quality from not a number to calling the is not a number function, and all will work as expected. We'll be able to get our eggs for $1.75 and the priceless bacon throws an exception because the number could not be parsed and was not a number.
So these have been some issues that you can encounter when using values, variables, and literals. Some of the issues we've discussed are trying to avoid using reserved words, being mindful that you aren't making global variables accidentally, trying to protect undefined from being redefined and also helping with minification, watching out for global DOM elements off the window and protecting yourself against the behavior, making sure you don't repeat object literal keys or function parameter names, trying to always provide a radix as the second parameter to parseInt so that octal isn't defaulted by accident, and trying to remember to use the is not a number function instead of trying to use the equality operator to test against not a number.
Pregnable Property Bug
In this pregnable property bug, we have a web page where we're pulling in mootools and we have an array of customers. Then we have a for in loop that will console.log the key and the customer. Do you know what the output will be? Can you spot the bug? (Pausing to spot bug) So here's the output from our previous buggy code. Whoa, isn't that crazy? Where did all this stuff come from? That wasn't in our array, what's going on? Well it turns out the for loop iterates over all the enumerable properties of an object, including those that are inherited from its prototype, and since an array is just a special type of object, then the Array's prototype gets enumerated as well. One of the issues with the previous code is that we had MooTools on the page. MooTools in of itself isn't bad, but it does do something that we need to be careful about as we code. Both MooTools and Prototype.js add custom prototype methods to the Array, String, and other constructors, and by doing so, if you use for in on an array, it'll also pick up the message that added to that Array prototype. For example, in the following code we have an array with test1 and test2 inside of it, and then we're adding a wat property on the Array.prototype. When we for in over our Array, we console 0 test1, 3 test2, and wat WAT!?! So you can see how it's picking up the item we added to the prototype. You may also notice that it didn't iterate over index 1 or 2. The for in doesn't pick up those because they aren't part of the object. As an alternative to using for in on an array, we could have just used a standard for loop instead, that way you have full control over what index you want to examine. The output we get using this approach is much more expected. We don't accidentally loop over the prototype property and we also get to see all the indexes as is usually expected when looping over an array. So the for in loop is more suited towards iterating over an object than an array, however, you still need to be mindful of the prototype. In the following code snippet we're defining a Person constructor function and assigning a married property onto the Person.prototype, then we're newing up a new John Person, setting his marital status to true, and then doing a for in loop over his properties. As you can see, not only did it pick up his name, but also the married property on its prototype. This may or may not be what you want, it could be that you only wanted the immediate properties and not those on the prototype. If that's the case, then you can call a special method off the object called hasOwnProperty. By calling this method, we could check if this object directly owns the property, or if it's something that's inherited from a prototype. In this case, we only console.log a message if the object owns the property, and now our console will only output the name and not console.log the married prototype property. So there are two ways we could have solved this problem. One is to keep using the for in loop on the array, but to call the hasOwnProperty before logging a message. By doing so you get the following output. Or, you could instead use a standard for loop, controlling your own index, that way you could iterate over every index, which is usually what you want when you're looping over an array. Here is the output using that technique. Note, you could also use the for each method is ECMAScript 5 to iterate over the array as well, or use various each utility methods off of jQuery or Underscore. In addition, JSHint helps us out here a little bit and will remind us to use the hasOwnProperty method if we're using the for in loop as seen in this screenshot.
Pregnable Property Bug: Demo
So here we have the pregnable property bug in JSFiddle. You're welcome to follow along in the URL above, but we're pulling in MooTools the library, and here we have an array of customers with John Smith, Susan Smith, and Jane Smith. We're using a for in loop and we're console logging the key and the particular customer that we're iterating over. So if we look in our console we have 0 John Smith, 1 Susan Smith, and 10 Jane Smith. First of all, it's kind of missing some of the indexes that we might need or may not need, and also it has tons and tons and tons and tons of other stuff in the console. That stuff is being picked up by MooTools because MooTools is adding a whole bunch of methods and properties onto the array prototype, and the for in loop will actually iterate not only over the items on the customers, but also on the prototype. So we probably don't want to iterate over those things, and what we could do, thankfully, is we could call customers.hasOwnProperty, which is a special method, and we'll pass in the key that we're using, and we'll basically ask it hey, this key that we're iterating over, do you actually own it on this particular object or is it being inherited from the prototype? And in this case we only want the ones that own the property on the object, we're going to ignore the ones that are bleeding in through the prototype. So if I run this again, now we'll only get the items for this particular object and not the ones in the prototype, so it's nice. Another way you could do this is just have a standard for loop, so we're going to have i and len, and then we're going to have a standard for statement, i = 0, and then we're going to say len = customers.length and i is less than len and then i++, and then inside of here we'll just console.log i, and then we'll have customers sub i. We'll run this code and here we're actually picking up all the indexes that are undefined, so you may or may not want those. Another way we could have done this is we could have used for each, which is an ECMAScript 5 function, and then inside of it we would accept the customer parameter, and we could just console.log the customer. And actually there's an index it'll pass us if we want to pick that up as well. Now the thing with for each, for each will actually not iterate over items that are undefined, and so you'll see when we run this, we only get John Smith, Susan Smith, and Jane Smith, kind of like the for in loop above, the output is similar, but they're behaving very different. So, just keep those in mind for various ways to loop over things, especially the hasOwnProperty is a very interesting method, and usually the for in loop is intended for objects you'll find, and if you have arrays you'll probably want to either use one of the following two techniques.
Accidental Ancestry Bug
For the accidental ancestry bug we have an Animal constructor function with a name property and eat and sleep prototype methods, and then we have a Cat constructor that inherits from the Animal.prototype. The Cat overrides the eat method wherein the Cat immediately falls asleep after eating. Can you spot the bug? (Pausing to spot bug) Well the problems with our code aren't obvious until we start creating other animals, like Dog for example. Let's create a Dog that inherits from Animal, and then will override its sleep method, and let's say these dogs are mean so they're going to attack humans before they sleep. And now we're going to switch gears and create a sweet, calm little Cat named Fluffy, and have it eat some food. And here's the output. Fluffy starts to eat like we expected, and then bam, our sweet little kitten is now attacking me, ah, take cover! So, what exactly is going on here? Well, since we assigned Animal.prototype to the Dog.prototype, we essentially are now sharing the same reference. So when we modified the sleep method, we weren't overriding it, we were re-riding it. Our next problem can be viewed down here. If we use the instanceof operator on our Cat instance, it'll return true to being an instance of an Animal and a Cat, which is great. However, if we compare what constructor was used to create it, it thinks it was created with the Animal constructor. It would be nice if it would tell us that it was created with a Cat constructor instead. So let's see what it would take to fix these two issues. It turns out that fixing these issues is pretty easy to do. In order to break the connection between the subtype and the supertype, all you have to do is create a new instance of the super prototype and assign it to the SubType's prototype. That way if you change the SubType you aren't also changing the SuperType, which is what was happening in our previous slide. The next thing we need to fix is the constructor. That's also an easy thing to fix, we just set the SubType's prototype constructor to the SubType constructor function. And now when we create a new subtype, the instanceof will be correct as we saw before, but now the SubType constructor will be equal to the subType.constructor function. Yea! So in order to fix our problem, we just need to make two minor changes, we need to Object.create our Animal.prototype when assigning it to Cat's prototype, and we need to set the Cat.prototype constructor to the Cat constructor function. And that's it. As a side note, you may have noticed some redundant code in the previous example. Well, if we have a subtype, then in the constructor we can call the SuperTypes constructor by saying Animal.prototype.constructor.call this, name. Yeah, that's a lot to type, but it's better than repeating the functionality again. In addition, if you're overriding a method and want to call the supers version of that method, for example in the eat method, then you could call Animal.prototype.eat.apply this. Again, that's nice so you don't have to repeat the code in your subclass.
Accidental Ancestry Bug: Demo
So what we have here is the accidental ancestry bug in JSFiddle, you're welcome to follow along at the URL above. So what we have here is an Animal constructor function with a name, and we have two methods, eat and sleep. And then we have a Cat constructor function and we're inheriting from Animal, and we're going to override the eat method and say that the cat is eating, and then the cat immediately goes to sleep, because that's what cats do. And then we'll have a Dog constructor function, it'll inherit from the Animal, and we're going to override its sleep method and the dog is going to attack a human before it goes to sleep, because that's what dogs do. And then we'll create a new instance of Cat, let it eat, create a new instance of Dog, and let it sleep. And then we have some additional console.logs, but we'll take a look at those in a minute. So let's come down to our dev tools, we'll look at our cat, our cat starts eating, but then wait a second, it starts attacking humans, what's it doing, that's kind of weird, but then it goes to sleep. And the dog behaves like we want it to, it attacks humans and then it goes to sleep. So we need to fix that code somehow, but before we do let's look at these last logs and see what it's talking about. So there's an instanceof operator, and the cool thing is we can say cat, are you an instanceof an Animal, and the answer is yes. And we can say cat, are you an instanceof a Cat, the answer is yes. But if we want to actually figure out who created this particular object, if we look at the constructor, cat.constructor are you the Animal, that's true. We would rather have cat.constructor equal to Cat be true. So we would like to flip these last two so we could actually figure out which constructor actually created this object. So those are the two things we're going to try to fix, one to make a cat not attack people, and two, to make the constructor logic correct. So the reason the cat is attacking someone is because when we looked at the dog down here, when we actually told it what to inherit from, we said Animal.prototype, we're going to assign you to the Dog's prototype. So essentially at that moment the reference for Dog.prototype is now the Animal.prototype. So when we go to change the behavior of sleep, we're actually changing the behavior of the animal's sleep. And so Cat is inheriting from Animal, so now the Cat is picking up whatever we changed down here, so now he's going to attack. So the way to get around this is when you actually set the prototypes you want to say Object.create, so you're creating an instance of the Animal.prototype and assigning that instance back to the Cat's prototype. We'll do the same thing for the Dog, and essentially this is breaking that tight bind between the two. So now if we come back over here and run our code again, the cat will no longer be attacking us because now it's separate, which is good. So in order to fix the constructor, what we're going to do is we're actually going to tell it which constructor it used, and so in this case we're going to say it used a Cat. And then we'll use the same technique for the Dog, change Dog here, and we used a Dog constructor function there. And so now we'll run this code and now these last two have flipped, which is good, so now the Cat constructor is using the Cat constructor function, true. One other thing that we're going to do before we stop is you might have noticed a lot of repetitive code. So for example our Cat constructor is running the same code as our Animal constructor does, but if it's inheriting it, why is it repeating the code? So let's get rid of that and what we're going to do is we're going to say Animal.prototype.construtor.apply this, and we're going to pass the arguments that the Cat constructor got. We're going to use the same technique for the Dog because the Dog was repeating the same code too. So now if the code in our Animal constructor changes, we don't have to actually change code in the Cat or the Dog. So I'll run this code and make sure everything still works. That's good. So the other thing we repeated is when we overrode the eat method, we actually repeated the code that was in the inherited method. So wouldn't it be nice if we didn't do that? So we're going to say Animal.prototype.sleep, and then we're going to apply and pass this. And we will do the same technique for when we over override sleep. So let's remove this, we'll come over here and we'll, so now we'll run our code again and everything works just as expected, but now we have reduced duplication, we have made it so the objects are separated, and we've also made it so the constructors are fixed.
Eccentric Envelope Bug
Eccentric Envelope Bug: Demo
In this eccentric envelope bug we have a contestants array and we have an isWinner function. At the bottom we're going to call isWinner twice, one passing in Elijah Manor as the name and the winner as false, and the other one we're going to pass in name of John Smith and winner as true. So what the function is supposed to do, it's supposed to look to see if the name that we pass is actually in the contestants array to make sure they're not cheating, and then we'll double check if they said they won or not. So if their name is actually in the contestants array and they said they won, then they get a smiley face, but if their name is not in the contestants array, or they said they're not a winner, then they get a frowny face. So if we run our code we actually see two frowny faces, Elijah Manor frowny, John Smith frowny. But we kind of expected John Smith to actually win, because John Smith's name is in here and he said he was a winner, so why didn't he get a smiley face? Well the main problem with this piece of code is we're using the object wrappers, String and Boolean, and that unfortunately confuses things quite a bit, especially when we start using the triple equals operator and not the double equals. We've already talked about how the double equals is kind of confusing, in many cases it does a lot of type coercions and you could follow the rules if you know the rules, but if you don't it could get very confusing. So what's happening here on the one that should of worked is we're passing in a John Smith String wrapper and a Boolean String wrapper with true in it, we come into the isWinner function, passing in our person, we're going to call contestants.some, and it's going to loop over and figure out if any of these are true. The name is our String wrapper and we're going to compare it to the contestant, which is one of the strings in our array. So a contestant will be a native string, and we're going to triple compare it to person.name, which is a String wrapper. If we use the triple equals, if the types are different, then it's going to be false, and in this case one's an object, one's a string, so it's always going to be false. And so that's why it's not going to work. So one way to fix this is to just get rid of the String wrappers. And for the most part it's usually a best case not to use the Boolean wrappers as well because you could get into some strange issues there, so let's just take out all these and we'll run again, and now we get Elijah Manor frowny, but John Smith smiley, yea, he won. So the main thing to think about here is just try to avoid these wrappers. So we're going to switch to JS Console here for just a minute and talk about when you might want to use the constructor functions for Boolean, String, and Number, and you might want to use Boolean if you want to convert things to a Boolean. So for example we talked about things that are falsey, so obviously false is falsey, but let's talk about empty string we actually about as falsely, so we'll actually get a false there, 0 is falsey. Things that are truthy are anything that aren't those 7 that we talked, so the number 5 for example, that would be truthy, and we could see those there. Another way to make sure if things are falsey or not, if you don't want to use the Boolean wrapper, is the not not. So if i not notted 5, that's true. The reason that works, we've talked about this before, but if I had 5 and I not it, then that converts it to a Boolean, but then flips the bit to false, but we really wanted the original value so we have to flip it again and get the original one. If we wanted to convert a number to a string we could use the String constructor wrapper and we could pass something into it like a 42, and you notice we get a 42 there. Another way is we could have concatenated a string that gives us a string as well. The reason that works is the plus operator, if either side is a string it will convert the other side to a string, so that's why that works. And here's a really weird one. If we say 42..toString, that will actually give us the string 42. Now why period period? Well if it sees the first period it thinks that's the decimal, but as soon as it sees another period, then it's like oh, that's something special, it'll actually convert that into a number using the Number constructor, and it has a toString method on it and it was able to convert it to 42. Now if we have a string and want to move it to a number, we could just put up the plus operator before a number, and that will convert it to an actual primitive number, so 42 right there, or we could use the Number constructor function wrapper and pass in the string 42, that converts it to a number. And then we know about parseInt whereas we could pass in a string, and we want to make sure we pass the radix as we talked about in a previous one, and then I'll parse to it 42. Now you might wonder, well which one should I use, parseInt, number or the plus operator, or there's a parseFloat for example. Well parseInt is a little more flexible where if I had something called 42 is the answer, and I passed in 10 as my radix, then it'll actually be smart enough and pick up all the numbers until it reaches something that it doesn't recognize as a number. So it'll still pick up 42, where if I tried one of these other techniques, 42 is the answer, then it'll just kind of give up and say not a number. So those are some use cases when you might want to use the wrappers, constructor wrappers, but of course there's other alternative so you're not limited to those, you could use the other ones instead.
Translate Time Bug
In the following translate time bug, we have some sample data that we're pretending is coming back from the server, and then we're using the ECMAScript 5 map method to iterate over the items and slightly transform what each record will look like. Instead of having uppercase Name we'll lowercase the name, and instead of having uppercase Birthday, we'll lowercase the birthday, and we'll also new up an instance of the date object based on what was passed from the server. Can you spot the bug? Do you know what will happen? (Pausing to spot bug) Well it turns out there isn't an error at all, but the result we get is not what we want. What we end up getting is an array that looks something like this. We were able to transform the keys to lowercase, which is good, name and birthday, but if you notice, the values of the birthdays, they say Invalid Date. Hmm, that's not so good. So what's the problem? Well in this case the date came from an older version of .NET, and it serialized the date to some strange Unix Epoch value with some strange extra information stuck in there. If we try to pass that to the Date constructor, it can't figure out what we meant, so it ends up being Invalid Date. Thankfully there's a nice utility date library called Moment.js, which allows us to convert this format for us. We'll see in our next slide how it can help us out even more. Thankfully with Moment.js it was really easy to fix this issue, we just pass the serialized date string into the Moment.js function, and then call the toDate method, and voila, the output looks much better. We have updated keys and a correctly parsed date. Yea, Moment.js! In addition to parsing older serialized .NET dates, there are many other handy features that Moment.js can do. I can format dates, and you could choose from a lot of different formats or create your own. It has a timeago feature, which basically means relative time, so you could see if a date is 2 years ago or 32 minutes ago, or in 28 minutes. Many social programs display their dates like this. And there are a bunch of calendar time methods like adding and subtracting amounts of time to or from an existing date. There's so much more you could do with the library. If you need to do stuff with dates, this is my go-to library. It's small and jam-packed with date goodness.
Perpetual Property Bug
Strange Set Bug
For this strange set bug we have two new arrays, one for an easyCombination with one number, and one for a hardCombination with three numbers. Then we decided we want to combine the easy and the hard arrays to generate a combined combination array. Finally, we console.log the array. Do you know what the resulting combined array will look like? Can you spot the bug? (Pausing to spot bug) This is actually kind of a weird one. Here's the output of the combined array. What? Does that even make sense at all? I was expecting an array of four items in it. What's even going on here? Well as it turns out, the Array constructor is overloaded, so depending on what parameters you pass it, it'll behave differently. If you new up a new array with no parameters, then it just creates a new empty Array. If you provide several arguments to the Array constructor, it'll new up an Array initialized with all those elements. So in these examples there are three items in each array, however, there's another overload where if there's only one argument and it happens to be a number, then that means something very special. It means that you want an array with that many entries that are all set to undefined, which seems a little strange to me. In order to fix this, we'll just use array literals instead of the Array constructor. And as you can see, the output is much more reasonable. It's a new array with four items from both arrays above. There is varied help with JSHint and JSLint about this particular issue. If you're using new Array to make an empty array, both linters will encourage you to use the array literal syntax, the square brackets. If you're using the special numeric 1 argument overload of the array, then neither of them will complain. They understand this means something special, so they'll let you do it. And in a similar fashion, the linters will encourage you to use the literal syntax if you're using the new Array to pass multiple arguments.
Malformed Message Bug
In this malformed message bug we have a string of JSON from the server, and then we go to parse it using JSON's parse method, and then we'll console.log what we parsed. Do you know what will happen? Can you spot the bug? (Pausing to spot bug) Well, all we get in our console is a big red exception, Uncaught SyntaxError: Unexpected token n. Umm, what does that even mean? It seems kind of cryptic, doesn't it? Well, as it turns out, the format of our JSON was incorrect. JSON, which is a string, is different from an object literal, which is an object. JSON is actually a subset of the object literal notation. So what does that mean? Well, JSON keys need to be double quoted and JSON strings need to be double quoted. Here's an example of both. You'll notice that the keys in obj1 are not quoted, whereas the keys in json string are double quoted. Also, the string in obj1 are single quotes, whereas the keys in the json string are double quotes. Object literals are much more flexible, I could have single quoted or double quoted all of its keys, or decided to double quote the strings if I wanted to. Quotes around keys in an object literal are optional unless there's a special character in them that's not valid in an identifier, or a variable name, which brings me to another point. There is no such thing as a JSON object. JSON is a string, it's not an object. It represents serialized data that typically comes from the server, but you could also store it in other places. So in order to fix our problem, we'll fix our JSON and use double quotes where they're necessary. As a side note, hopefully you aren't manually creating all of your JSON by hand, or rote code to generate your JSON with string concatenation or a template. There are great open source JSON serializers in most languages and libraries, and many that are native with server technologies. It's considered best to use these and not try to output or tweak your own. By doing so, hopefully you won't run into this problem. Anyway, once we fix our issue then the code works just like we expected. Here's the parsed object in our console.
Malformed Message Bug: Demo
Here's the code for our malformed message bug, we're in JSFiddle and you're welcome to follow along in the URL above. What we have here is the dataFromServer string, which represents our JSON that we're simulating coming back from the server, and then we're trying to parse it using JSON.parse, and then we're going to log in to our console using JSON.stringify. If we run the code we'll immediately get an error saying SyntaxError: Unexpected token n, which is not very descriptive. But if we look at our JSON, it's not actually valid JSON. JSON has quotes around all of its key names, and if there are strings it has to use double quotes, it can't use single quotes. So for example, let's come back in here and change some things around. Since I know I'm going to have double quotes inside, I'm going to use single quotes outside. So we have to double quote our keys, and then I'm going to double quote our strings. So here's the key I have to double quote, and then here I have to double quote my string, and double quote this other string. Now age is a key so I have to double quote it. Now number is 28, I do not have to quote it. So if I run my code again, sure enough it parses it, I do not get an error, and then when I stringify it and format it a little bit, then it will print out accordingly. Now with object literals they're a little bit different. Let's take this and make an object literal. I can essentially take the contents of what was in my JSON and it could be a valid object literal. Now there are subtle differences where I don't have to have quotes around my keys if I don't want to, as long as they're a valid identifier. So I could decide to take off these quotes if I wanted to, or I could have single quotes if I wanted to, they're pretty flexile as the keys. Now if I had a special character like a dash, like na-me, then I would have to put quotes around it, or single quotes. But as long as it doesn't have anything special around it you could just take the quotes off. Now our strings for an object literal, we could use either double quotes or single quotes, it doesn't matter, however, JSON is much more strict, and so you kind of have to follow those guidelines. So it's important to know the distinction between the two, and hopefully you're not manually coding this, hopefully your JSON comes from the server with some kind of a special library.
Elijah Manor is a Christian and a family man. He is a Microsoft Regional Director, Microsoft ASP.NET MVP, ASPInsider, and IE userAgent and specializes in front-end web development. He enjoys...
Released21 Aug 2013