Thereâs more to JavaScript than numbers, strings and booleans. So far youâve been writing JavaScript code with primitivesâsimple strings, numbers and booleans, like âFidoâ, 23, and true. And you can do a lot with primitive types, but at some point youâve got to deal with more data. Say, all the items in a shopping cart, or all the songs in a playlist, or a set of stars and their apparent magnitude, or an entire product catalog. For that we need a little more ummph. The type of choice for this kind of ordered data is a JavaScript array, and in this chapter weâre going to walk through how to put your data into an array, how to pass it around and how to operate on it. Weâll be looking at a few other ways to structure your data in later chapters but letâs get started with arrays.
Meet the Bubbles-R-Us company. Their tireless research makes sure bubble wands & machines everywhere blow the best bubbles. Today theyâre testing the âbubble factorâ of several variants of their new bubble solution; that is, theyâre testing how many bubbles a given solution can make. Hereâs their data:
Of course you want to get all this data into JavaScript so you can write code to help analyze it. But thatâs a lot of values. How are you going to construct your code to handle all these values?
You know how to represent single values like strings, numbers and booleans with JavaScript, but how do you represent multiple values, like all the bubble factor scores from the ten bubble solutions? To do that we use JavaScript arrays. An array is a JavaScript type that can hold many values. Hereâs a JavaScript array that holds all the bubble factor scores:
You can treat all the values as a whole, or you can access the individual scores when you need to. Check this out:
Before we get on to helping Bubbles-R-Us, letâs make sure weâve got arrays down. As we said, you can use arrays to store multiple values (unlike variables that hold just one value, like a number or a string). Most often youâll use arrays when you want to group together similar things, like bubble factor scores, ice cream flavors, daytime temperatures or even the answers to a set of true/false questions. Once you have a bunch of values you want to group together, you can create an array that holds them, and then access those values in the array whenever you need them.
Letâs say you wanted to create an array that holds ice cream flavors. Hereâs how youâd do that:
When you create an array, each item is placed at a location, or index, in the array. With the flavors array, the first item, âvanillaâ, is at index 0, the second, âbutterscotchâ, is at index 1, and so on. Hereâs a way to think about an array:
Each item in the array has its own index, and thatâs your key to both accessing and changing the values in an array. To access an item just follow the array variable name with an index, surrounded by square brackets. You can use that notation anywhere youâd use a variable:
You can also use the array index to change a value in an array:
So, after this line of code, your array will look like this:
Say someone hands you a nice big array with important data in it. You know whatâs in it, but you probably wonât know exactly how big it is. Luckily, every array comes with its own property, length
. Weâll talk more about properties and how they work in the next chapter, but for now, a property is just a value associated with an array. Hereâs how you use the length
property:
We hope you figured out this code is the perfect tool for creating your next start-up marketing slogan. It has created winners like âWin-win value-added solutionâ and â24/7 empowered processâ in the past and we have high hopes for more winners in the future. Letâs see how this thing really works:
First, we define the
makePhrases
function, which we can call as many times as we want to generate the phrases we want:With that out of the way we can write the code for the
makePhrases
function. Letâs start by setting up three arrays. Each will hold words that weâll use to create the phrases. In the next step, weâll pick one word at random from each array to make a three word phrase.Now we generate three random numbers, one for each of the three random words we want to pick to make a phrase. Remember from Chapter 2 that Math.random generates a number between 0 and 1 (not including 1). If we multiply that by the length of the array, and use Math.floor to truncate the number, we get a number between 0 and one less than the length of the array.
Now we create the slick marketing phrase by taking each randomly chosen word and concatenating them all together, with a nice space in between for readability:
Weâre almost done; we have the phrase, now we just have to display it. Weâre going to use
alert
as usual.alert(phrase);
Okay, finish that last line of code, have one more look over it all and feel that sense of accomplishment before you load it into your browser. Give it a test drive and enjoy the phrases.
Letâs take a closer look at what the CEO is looking for:
Brain Power
Take some time to sketch out your ideas of how youâd create this little bubble score report. Take each item in the report separately and think of how youâd break it down and generate the right output. Make your notes here.
Judy:Â The first thing we need to do is display every score along with its solution number.
Joe:Â And the solution number is just the index of the score in the array, right?
Judy:Â Oh, yeah, thatâs totally right.
Frank:Â Slow down a sec. So we need to take each score, print its index, which is the bubble solution number, and then print the corresponding score.
Judy:Â Youâve got it, and the score is just the corresponding value in the array.
Joe:Â So, for bubble solution #10, its score is just scores[10]
.
Judy:Â Right.
Frank:Â Okay, but there are a lot of scores. How do we write code to output all of them?
Judy:Â Iteration, my friend.
Frank:Â Oh, you mean like a while loop?
Judy:Â Right, we loop through all the values from zero to the length... oh, I mean the length minus one of course.
Joe:Â This is starting to sound very doable. Letâs write some code; I think we know what weâre doing.
Judy:Â That works for me! Letâs do it, and then weâll come back to the rest of the report.
Your goal is to produce some output that looks like this:
Weâll do that by outputting the score at index zero, and then weâll do the same for index one, two, three and so on, until we reach the last index in the array. You already know how to use a while loop; letâs see how we can use that to output all the scores:
We should really apologize. We canât believe itâs already Chapter 4 and we havenât even introduced you to the for loop. Think of the for loop as the while loopâs cousin. The two basically do the same thing, except the for loop is usually a little more convenient to use. Check out the while loop we just used and weâll see how that maps into a for loop.
Now letâs look at how the for loop makes all that so much easier:
Youâve been writing lots of code that looks like this:
In fact, this statement is so common thereâs a shortcut for it in JavaScript. Itâs called the post-increment operator, and despite its fancy name, it is quite simple. Using the post-increment operator, we can replace the above line of code with this:
Of course it just wouldnât feel right if there wasnât a post-decrement operator as well. You can use the post-decrement operator on a variable to reduce its value by one. Like this:
And why are we telling you this now? Because itâs commonly used with for
statements. Letâs clean up our code a little using the post-increment operator...
Time to do a quick test drive to make sure the change to use the post-increment operator works. Save your file, âbubbles.htmlâ, and reload. You should see the same report you saw before.
Judy:Â Right, and the first thing we need to do is determine the total number of bubble tests. Thatâs easy; itâs just the length of the scores array.
Joe:Â Oh, right. Weâve got to find the highest score too, and then the solutions that have the highest score.
Judy:Â Yeah, that last one is going to be the toughest. Letâs work out finding the highest score first.
Joe:Â Sounds like a good place to start.
Judy:Â To do that I think we just need to maintain a highest score variable that keeps track as we interate through the array. Here, let me write some pseudocode:
Joe:Â Oh nice; you did it with just a few lines added to our existing code.
Judy:Â Each time through the array we look to see if the current score is greater than highScore
, and if so, thatâs our new high score. Then, after the loop ends we just display the high score.
âMore than oneâ...hmmm. When we need to store more than one thing what do we use? An array, of course. So can we iterate through the scores array looking for only scores that match the highest score, and then add them to an array that we can later display in the report? You bet we can, but to do that weâll have to learn how to create a brand new, empty array, and then understand how to add new elements to it.
Before we take on finishing this code, letâs get a sense for how to create a new array, and how to add new items to it. You already know how to create an array with values, like this:
But you can also omit the initial items and just create an empty array:
And you already know how to add new values to an array. To do that you just assign a value to an item at an index, like this:
Now when adding new items you have to be careful about which index youâre adding. Otherwise youâll create a sparse array, which is an array with âholesâ in it (like an array with values at 0 and 2, but no value at 1). Having a sparse array isnât necessarily a bad thing, but it does require special attention. For now, thereâs another way to add new items without worrying about the index, and thatâs push
. Hereâs how it works:
Judy:Â Yes, weâll start with an empty array to hold the solutions with the highest scores, and add each solution that has that high score one at a time to it as we iterate through the scores array.
Frank:Â Great, letâs get started.
Judy:Â But hold on a second... I think we might need a separate loop.
Frank:Â We do? Seems like there should be a way to do it in our existing loop.
Judy:Â Yup, Iâm sure we do. Hereâs why. We have to know what the highest score is before we can find all the solutions that have that highest score. So we need two loops: one to find the highest score, which weâve already written, and then a second one to find all the solutions that have that score.
Frank:Â Oh, I see. And in the second loop, weâll compare each score to the highest score, and if it matches, weâll add the index of the bubble solution score to the new array weâre creating for the solutions with the highest scores.
Judy:Â Exactly! Letâs do it.
Brain Power
Take a look at the code in the Sharpen exercise above. What if you woke up and push no longer existed? Could you rewrite this code without using push? Work that code out here:
Go ahead and add the code to generate the bubble solutions with the highest score to your code in âbubbles.htmlâ and run another test drive. All the JavaScript code is shown below:
var scores = [60, 50, 60, 58, 54, 54, 58, 50, 52, 54, 48, 69, 34, 55, 51, 52, 44, 51, 69, 64, 66, 55, 52, 61, 46, 31, 57, 52, 44, 18, 41, 53, 55, 61, 51, 44]; var highScore = 0; var output; for (var i = 0; i < scores.length; i++) { output = "Bubble solution #" + i + " score: " + scores[i]; console.log(output); if (scores[i] > highScore) { highScore = scores[i]; } } console.log("Bubbles tests: " + scores.length); console.log("Highest bubble score: " + highScore); var bestSolutions = []; for (var i = 0; i < scores.length; i++) { if (scores[i] == highScore) { bestSolutions.push(i); } } console.log("Solutions with the highest score: " + bestSolutions);
Bubble solutions #11 and #18 both have a high score of 69! So they are the best bubble solutions in this batch of test solutions.
Youâre right, we should be. Given you just learned functions, we wanted to get the basics of arrays out of the way before employing them. That said, you always want to think about which parts of your code you can abstract away into a function. Not only that, but say you wanted to reuse, or let others reuse, all the work that went into writing the bubble computationsâyouâd want to give other developers a nice set of functions they could work with.
Letâs go back to the Bubble Score code and refactor it into a set of functions. By refactor we mean weâre going to rework how itâs organized, to make it more readable and maintainable, but weâre going to do it without altering what the code does. In other words, when weâre done, the code will do exactly what it does now but itâll be a lot better organized.
Letâs get an overview of the code weâve written and figure out which pieces we want to abstract into functions:
Weâve got the code for the printAndGetHighScore
function already. Itâs just the code weâve already written, but to make it a function we need to think through what arguments weâre passing it, and if it returns anything back to us.
Now, passing in the scores array seems like a good idea because that way, we can reuse the function on other arrays with bubble scores. And we want to return the high score that we compute in the function, so the code that calls the function can do interesting things with it (and, after all, weâre going to need it to figure out the best solutions).
Oh, and another thing: often you want your functions to do one thing well. Here weâre doing two things: weâre displaying all the scores in the array and weâre also computing the high score. We might want to consider breaking this into two functions, but given how simple things are right now weâre going to resist the temptation. If we were working in a professional environment we might reconsider and break this into two functions, printScores
and getHighScore
. But for now, weâll stick with one function. Letâs get this code refactored:
Now, we need to change the rest of the code to use our new function. To do so, we simply call the new function, and set the variable highScore
to the result of the printAndGetHighScore
function:
Once youâve completed refactoring your code, make all the changes to âbubbles.htmlâ, just like we have below, and reload the bubble report. You should get exactly the same results as before. But now you know your code is more organized and reusable. Create your own scores array and try some reuse!
So, whatâs the job here? Itâs to take the leading bubble solutionsâthat is, the ones with the highest bubble scoresâand choose the lowest cost one. Now, luckily, weâve been given a costs
array that mirrors the scores
array. That is, the bubble solution score at index 0 in the scores
array has the cost at index 0 in the costs
array (.25), the bubble solution at index 1 in the scores
array has a cost at index 1 in the costs
array (.27), and so on. So, for any score youâll find its cost in the costs
array at the same index. Sometimes we call these parallel arrays:
Judy:Â Well, we know the highest score already.
Frank:Â Right, but how do we use that? And we have these two arrays, how do we get those to work together?
Judy:Â Iâm pretty sure either of us could write a simple for loop that goes through the scores
array again and picks up the items that match the highest score.
Frank:Â Yeah, I could do that. But then what?
Judy:Â Anytime we hit a score that matches the highest score, we need to see if its cost is the lowest weâve seen.
Frank:Â Oh I see, so weâll have a variable that keeps track of the index of the âlowest cost high score.â Wow, thatâs a mouthful.
Judy:Â Exactly. And once we get through the entire array, whatever index is in that variable is the index of the item that not only matches the highest score, but has the lowest cost.
Frank:Â What if two items match in cost?
Judy:Â Hmm, we have to decide how to handle that. Iâd say, whatever one we see first is the winner. Of course we could do something more complex, but letâs stick with that unless the CEO says differently.
Frank:Â This is complicated enough I think I want to sketch out some pseudocode before writing anything.
Judy:Â I agree; whenever you are managing indices of multiple arrays things can get tricky. Letâs do that; in the long run Iâm sure it will be faster to plan it first.
Frank:Â Okay, Iâll take a first stab at it...
Get Head First JavaScript Programming now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.