Functions, Arrays, and Objects - Client-Side Programming with JavaScript - HTML5 and CSS3 All-in-One For Dummies (2014)

HTML5 and CSS3 All-in-One For Dummies (2014)

Book IV Client-Side Programming with JavaScript

Chapter 4 Functions, Arrays, and Objects

In This Chapter

arrow Passing parameters into functions

arrow Returning values from functions

arrow Functions and variable scope

arrow Producing basic arrays

arrow Retrieving data from arrays

arrow Building a multidimensional array

arrow Creating objects

arrow Building object constructors

arrow Introducing JSON notation

It doesn't take long for your code to become complex. Soon enough, you find yourself wanting to write more sophisticated programs. When things get larger, you need new kinds of organizational structures to handle the added complexity.

You can bundle several lines of code into one container and give this new chunk of code a name: a function. You can also take a whole bunch of variables, put them into a container, and give it a name. That's called an array. If you combine functions and data, you get another interesting structure called an object.

You may have encountered variables and functions in their simplest forms elsewhere in this book (variables were first introduced in Chapter 1 of this minibook, and functions made their appearance in Chapter 2). This chapter is about how to work with more code and more data without going crazy.

Breaking Code into Functions

Functions come in handy when you're making complex code easier to handle — a useful tool for controlling complexity. You can take a large, complicated program and break it into several smaller pieces. Each piece stands alone and solves a specific part of the overall problem.

You can think of each function as a miniature program. You can define variables in functions, put loops and branches in there, and do anything else you can do with a program. A program using functions is basically a program full of subprograms.

technicalstuff.eps After you define your functions, they're just like new JavaScript commands. In a sense, when you add functions, you're adding to JavaScript.

To explain functions better, think back to an old campfire song, “The Ants Go Marching.” Figure 4-1 re-creates this classic song for you in JavaScript format. (You may want to roast a marshmallow while you view this program.)

9781118289389-fg2101.tif

Figure 4-1: Nothing reminds me of functions like a classic campfire song.

If you're unfamiliar with this song, it simply recounts the story of a bunch of ants. The littlest one apparently has some sort of attention issues. During each verse, the little one gets distracted by something that rhymes with the verse number. The song typically has ten verses, but I'm just doing two for the demo.

Thinking about structure

Before you look at the code, think about the structure of the song, “The Ants Go Marching.” Like many songs, it has two parts. The chorus is a phrase repeated many times throughout the song. The song has several verses, which are similar to each other, but not quite identical.

Think about the song sheet passed around the campfire. (I'm getting hungry for a s'more.) The chorus is usually listed only one time, and each verse is listed. Sometimes, you have a section somewhere on the song sheet that looks like the following:

Verse 1
Chorus
Verse 2
Chorus

Musicians call this a road map, and that's a great name for it. A road map is a high-level view of how you progress through the song. In the road map, you don't worry about the details of the particular verse or chorus. The road map shows the big picture, and you can look at each verse or chorus for the details.

Building the antsFunction.html program

Take a look at the code for antsFunction.html and see how it reminds you of the song sheet for “The Ants Go Marching”:

<!DOCTYPE html>
<html lang = "en-US">

<head>
<meta charset = "UTF-8">
<title>antsFunction.html</title>
<script type = "text/javascript">
//from antsFunction.html

var output;

function chorus() {
var text = "...and they all go marching down <br />";
text += "to the ground <br />";
text += "to get out <br />";
text += "of the rain. <br />";
text += " <br />";
text += "boom boom boom boom boom boom boom boom <br /><br />";
output.innerHTML += text;
} // end chorus

function verse1(){
var text = "The ants go marching 1 by 1 hurrah, hurrah <br />";
text += "The ants go marching 1 by 1 hurrah, hurrah <br />";
text += "The ants go marching 1 by 1 <br />";
text += " The little one stops to suck his thumb <br /><br />";
output.innerHTML += text;
} // end verse1

function verse2(){
var text = "The ants go marching 2 by 2 hurrah, hurrah <br />";
text += "The ants go marching 2 by 2 hurrah, hurrah <br />";
text += "The ants go marching 2 by 2 <br />";
text += " The little one stops to tie his shoe <br /><br />";
output.innerHTML += text;
} // end verse2

function makeSong(){
output = document.getElementById("output");
output.innerHTML = "";
verse1();
chorus();
verse2();
chorus();
} // end makeSong

</script>

</head>
<body>
<h1>Using Basic Functions</h1>
<form action = "">
<fieldset>
<button type = "button"
onclick = "makeSong()">
make song
</button>
</fieldset>
</form>

<div id = "output">
The song will appear here...
</div>

</body>
</html>

The program code breaks the parts of the song into the same pieces a song sheet does. Here are some interesting features of antsFunction.html:

· I created a function called chorus(). Functions are simply collections of code lines with a name.

· All the code for the chorus goes into this function. Anything I want as part of printing the chorus goes into the chorus() function. Later, when I want to print the chorus, I can just call the chorus() function and it will perform the code I stored there.

· Each verse has a function, too. I broke the code for each verse into its own function.

· The makeSong function is a road map. When all the details are delegated to the functions, the main part of the code just controls the order in which the functions are called. In this case, the makeSong() function is called by the button press, which runs all the other functions.

· Details are hidden in the functions. The makeSong code handles the big picture. The details (how to print the chorus or verses) are hidden inside the functions.

· I'm using standard form-based output. Each of the functions creates its own part of the song and adds it to the output as needed.

Passing Data to and from Functions

Functions are logically separated from each other. This separation is a good thing because it prevents certain kinds of errors. However, sometimes you want to send information to a function. You may also want a function to return some type of value. The antsParam.html page rewrites the “The Ants Go Marching” song in a way that takes advantage of function input and output.

<!DOCTYPE HTML>
<html lang = "en">
<head>
<title>param.html</title>
<meta charset = "UTF-8" />
<style type = "text/css">
</style>
<script type = "text/javascript">
//Ants to marching in using functions with parameters

function makeSong(){
//create output variable
var output = document.getElementById("output");

output.innerHTML = "";

output.innerHTML += verse(1);
output.innerHTML += chorus();
output.innerHTML += verse(2);
output.innerHTML += chorus();
} // end makeSong

function chorus(){
var result = "-and they all go marching down, <br />";
result += "to the ground, to get out, of the rain. <br />";
result += "boom boom boom boom <br />";
result += "boom boom boom boom <br />";
result += "<br />";
return result;
} // end chorus

function verse(verseNumber){
var distraction = "";
if (verseNumber == 1){
distraction = "suck his thumb";
} else if (verseNumber == 2){
distraction = "tie his shoe";
} else {
distraction = "there's a problem here...";
} // end if

var result = "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + "<br />";
result += "The little one stops to ";
result += distraction + "<br /><br /> ";

return result;
} // end verse

</script>

tip.eps I don't provide a figure of this program because it looks just like antsFunction.html to the user. One advantage of functions is that I can improve the underlying behavior of a program without imposing a change in the user's experience.

This code incorporates a couple of important new ideas. (The following list is just the overview; the specifics are coming in the following sections.)

· These functions return a value. The functions no longer do their own alerts. Instead, they create a value and return it to the main program.

· Only one verse function exists. Because the verses are all pretty similar, using only one verse function makes sense. This improved function needs to know what verse it's working on to handle the differences.

Examining the makeSong code

The makeSong code has been changed in one significant way. In the last program, the makeSong code called the functions, which did all the work. This time, the functions don't actually output anything themselves. Instead, they collect information and pass it back to the main program. Inside the makeSong code, each function is treated like a variable.

You've seen this behavior before. The prompt() method returns a value. Now the chorus() and verse() methods return values. You can do anything you want to this value, including storing it to a variable, printing it, or comparing it to some other value.

remember.eps If you have one function that controls all the action, often that function is called main(). Some languages require you to have a function called main(), but JavaScript isn't that picky. For this example, I went with makeSong() because that name is more descriptive thanmain(). Still, the makeSong() function is a main function because it controls the rest of the program.

technicalstuff.eps Separating the creation of data from its use as I've done here is a good idea. That way, you have more flexibility. After a function creates some information, you can print it to the screen, store it on a web page, put it in a database, or whatever.

Looking at the chorus

The chorus of “The Ants Go Marching” song program has been changed to return a value. Take another look at the chorus() function to see what I mean.

function chorus(){
var result = "-and they all came marching down, <br />";
result += "to the ground, to get out, of the rain. <br />";
result += "boom boom boom boom <br />";
result += "boom boom boom boom <br />";
result += "<br />";
return result;
} // end chorus

Here's what changed:

· The purpose of the function has changed. The function is no longer designed to output some value to the screen. Instead, it now provides text to the main program, which can do whatever it wants with the results.

· There's a variable called text. This variable contains all the text to be sent to the main program. (It contained all the text in the last program, but it's even more important now.)

· The text variable is concatenated over several lines. I used string concatenation to build a complex value. Note the use of break tags (<br />) to force carriage returns in the HTML output.

· The return statement sends text to the main program. When you want a function to return some value, simply use return followed by a value or variable. Note that return should be the last line of the function.

Handling the verses

The verse() function is quite interesting:

· It can print more than one verse.

· It takes input to determine which verse to print.

· It modifies the verse based on the input.

· It returns a value, just like chorus().

To make the verse so versatile (get it? verse-atile!), it must take input from the primary program and return output.

Passing data to the verse() function

The verse() function is always called with a value inside the parentheses. For example, the main program sets verse(1) to call the first verse, and verse(2) to invoke the second. The value inside the parentheses is called an argument.

The verse function must be designed to accept an argument (because I call it using values inside the parentheses). Look at the first line to see how.

function verse(verseNumber){

In the function definition, I include a variable name. Inside the function, this variable is known as a parameter. (Don't get hung up on the terminology. People often use the terms parameter and argument interchangeably.) The important idea is that whenever the verse() function is called, it automatically has a variable called verseNumber. Whatever argument you send to the verse() function from the main program will become the value of the variable verseNumber inside the function.

You can define a function with as many parameters as you want. Each parameter gives you the opportunity to send a piece of information to the function.

Determining the distraction

If you know the verse number, you can determine what distracts “the little one” in the song. You can determine the distraction in a couple ways, but a simple if-elseif structure is sufficient for this example.

var distraction = "";
if (verseNumber == 1){
distraction = "suck his thumb.";
} else if (verseNumber == 2){
distraction = "tie his shoe.";
} else {
distraction = "I have no idea.";
}

I initialized the variable distraction to be empty. If verseNum is 1, set distraction to "suck his thumb". If verseNumber is 2, distraction should be "tie his shoe". Any other value for verseNumber is treated as an error by the else clause.

technicalstuff.eps If you're an experienced coder, you may be yelling at this code. It still isn't optimal. Fortunately, in the section “Building a Basic Array” later in this chapter, I show an even better solution for handling this particular situation with arrays.

By the time this code segment is complete, verseNumber and distraction both contain a legitimate value.

Creating the text

When you know these variables, it's pretty easy to construct the output text:

var result = "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + "<br />";
result += "The little one stops to ";
result += distraction + "<br /><br /> ";

return result;
} // end verse

A whole lotta concatenating is going on, but it's essentially the same code as the original verse() function. This one's just a lot more flexible because it can handle any verse. (Well, if the function has been preloaded to understand how to handle the verseNumber.)

Managing Scope

A function is much like an independent mini-program. Any variable you create inside a function has meaning only inside that function. When the function is finished executing, its variables disappear! This setup is actually a really good thing. A major program will have hundreds of variables, and they can be difficult to keep track of. You can reuse a variable name without knowing it or have a value changed inadvertently. When you break your code into functions, each function has its own independent set of variables. You don't have to worry about whether the variables will cause problems elsewhere.

Introducing local and global variables

You can also define variables at the main (script) level. These variables are global variables. A global variable is available at the main level and inside each function. A local variable (one defined inside a function) has meaning only inside the function. The concept of local versus global functions is sometimes referred to as scope.

Local variables are kind of like local police. Local police have a limited geographical jurisdiction, but they're very useful within that space. They know the neighborhood. Sometimes, you encounter situations that cross local jurisdictions. This situation is the kind that requires a state trooper or the FBI. Local variables are local cops, and global variables are the FBI.

tip.eps Generally, try to make as many of your variables local as possible. The only time you really need a global variable is when you want some information to be used in multiple functions.

Examining variable scope

To understand the implications of variable scope, take a look at scope.html:

<script type = "text/javascript">
//from scope.html
var globalVar = "I'm global!";

function myFunction(){
var localVar = "I'm local";
console.log(localVar);
}

myFunction();
</script>

This program defines two variables. In the main code, globalVar is defined, and localVar is defined inside a function. If you run the program in debug mode while watching the variables, you can see how they behave. Figure 4-2 shows what the program looks like early in the run.

9781118289389-fg2102.tif

Figure 4-2: globalVar is defined, but localVar is not.

localVar doesn't have meaning until the function is called, so it remains undefined until the computer gets to that part of the code. Step ahead a few lines, and you see that localVar has a value, as shown in Figure 4-3.

9781118289389-fg2103.tif

Figure 4-3: localVar has a value because I'm inside the function.

tip.eps Be sure to use Step Into (down arrow) rather than Step Over (up arrow) on the “remote control” toolbar for this example. When Step Over encounters a function, it runs the entire function as one line rather than looking at the function code line by line. If you want to look into the function and see what's happening inside it (as you do here), use Step Into. Use Step Over when you know a function is working fine and you want to treat it as a single instruction. If in doubt, always use Step Into to see exactly what's happening in your code. (I added watch expressions to clarify the content of the variables.)

globalVar still has a value (it's an FBI agent), and so does localVar because it's inside the function.

If you move a few more steps, localVar no longer has a value when the function ends (see Figure 4-4).

9781118289389-fg2104.tif

Figure 4-4: Once again, localVar has no meaning.

Variable scope is a good thing because it means you have to keep track of only global variables and the variables defined inside your current function. The other advantage of scope is the ability to reuse a variable name. You can have ten different functions all using the same variable name, and they won't interfere with each other because they're entirely different variables.

Building a Basic Array

If functions are groups of code lines with a name, arrays are groups of variables with a name. Arrays are similar to functions because they're used to manage complexity. An array is a special kind of variable. Use an array whenever you want to work with a list of similar data types.

The following code shows a basic demonstration of arrays:

<script type = "text/javascript">
//from genres.html

//creating an empty array
var genre = new Array(5);

//storing data in the array
genre[0] = "flight simulation";
genre[1] = "first-person shooters";
genre[2] = "driving";
genre[3] = "action";
genre[4] = "strategy";

//returning data from the array
alert ("I like " + genre[4] + " games.");
//]]
</script>

The variable genre is a special variable because it contains many values. Essentially, it's a list of genres. The new Array(5) construct creates space in memory for five variables, all named genre.

Accessing array data

After you specify an array, you can work with the individual elements using square-bracket syntax. An integer identifies each element of the array. The index usually begins with.

genre[0] = "flight simulation";

The preceding code assigns the text value “flight simulation” to the genre array variable at position 0.

technicalstuff.eps Most languages require all array elements to be the same type. JavaScript is very forgiving. You can combine all kinds of stuff in a JavaScript array. This flexibility can sometimes be useful, but be aware that this trick doesn't work in all languages. Generally, I try to keep all the members of an array the same type.

After you store the data in the array, you can use the same square-bracket syntax to read the information.

The line

alert ("I like " + genre[4] + " games.");

finds element 4 of the genre array and includes it in an output message.

Figure 4-5 shows a run of genres.html.

9781118289389-fg2105.tif

Figure 4-5: This data came from an array.

Using arrays with for loops

The main reason to use arrays is convenience. When you have a lot of information in an array, you can write code to work with the data quickly. Whenever you have an array of data, you commonly want to do something with each element in the array. Take a look at games.html to see how you can do so:

<script type = "text/javascript">
//from games.html

//pre-loading an array
var gameList = new Array("Flight Gear", "Sauerbraten", "Future Pinball",
"Racer", "TORCS", "Orbiter", "Step Mania", "NetHack",
"Marathon", "Crimson Fields");

var text = "";
for (i = 0; i < gameList.length; i++){
text += "I love " + gameList[i] + "\n";
} // end for loop
alert(text);
</script>

Notice several things in this code:

· The array called gameList. This array contains the names of some of my favorite freeware games.

· The array is preloaded with values. If you provide a list of values when creating an array, JavaScript simply preloads the array with the values you indicate. You don't need to specify the size of the array if you preload it.

· A for loop steps through the array. Arrays and for loops are natural companions. The for loop steps through each element of the array.

· The array's length is used in the for loop condition. Rather than specifying the value 10, I used the array's length property in my for loop. This practice is good because the loop automatically adjusts to the size of the array when I add or remove elements.

· Do something with each element. Because i goes from 0 to 9 (the array indices), I can easily print each value of the array. In this example, I simply add to an output string.

· Note the newline characters. The \n combination is a special character that tells JavaScript to add a carriage return, such as you get by pressing the Enter key. Figure 4-6 shows a run of games.html.

9781118289389-fg2106.tif

Figure 4-6: Now I have a list of games. Arrays and loops are fun!

tip.eps If you want to completely ruin your productivity, Google some of these game names. They're absolutely incredible, and every one of them is free. It's hard to beat that. See, even if you don't learn how to program in this book, you get something good from it!

Revisiting the ants song

If you read the earlier sections, you probably just got that marching ant song out of your head. Sorry. Take a look at the following variation, which uses arrays and loops to simplify the code even more.

<script type = "text/javascript">
//This old man using functions and arrays

var distractionList = Array("", "suck his thumb", "tie his shoe",
"climb a tree", "shut the door");

function makeSong(){
//create output variable
var output = document.getElementById("output");

output.innerHTML = "";
for (verseNumber = 1; verseNumber < distractionList.length; verseNumber++){
output.innerHTML += verse(verseNumber);
output.innerHTML += chorus();
} // end for loop

} // end makeSong

function chorus(){
var result = "-and they all came marching down, <br />";
result += "to the ground, to get out, of the rain. <br />";
result += "boom boom boom boom <br />";
result += "boom boom boom boom <br />";
result += "<br />";
return result;
} // end chorus

function verse(verseNumber){
var distraction = distractionList[verseNumber];

var result = "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + ", ";
result += "hurrah, hurrah <br />";
result += "The ants go marching ";
result += verseNumber + " by " + verseNumber + "<br />";
result += "The little one stops to ";
result += distraction + "<br /><br /> ";

return result;
} // end verse

</script>

This code is just a little different from the antsParam program shown in the section of this chapter called “Passing Data to and from Functions.”

· It has an array called distractionList. This array is (despite the misleading name) a list of distractions. I made the first one (element zero) blank so that the verse numbers would line up properly. (Remember, computers normally count beginning with zero.)

· The verse()function looks up a distraction. Because distractions are now in an array, you can use the verseNumber as an index to loop up a particular distraction. Compare this function to the verse() function in antsParam. This program can be found in the section “Passing data to and from Functions.” Although arrays require a little more planning than code structures, they can highly improve the readability of your code.

· The makeSong() function is a loop. I step through each element of the distractionList array, printing the appropriate verse and chorus.

· The chorus()function remains unchanged. You don't need to change chorus().

Working with Two-Dimension Arrays

Arrays are useful when working with lists of data. Sometimes, you encounter data that's best imagined in a table. For example, what if you want to build a distance calculator that determines the distance between two cities? The original data might look like Table 4-1.

2101

Think about how you would use Table 4-1 to figure out a distance. If you wanted to travel from New York to London, for example, you'd pick the New York row and the London column and figure out where they intersect. The data in that cell is the distance (3,470 miles).

When you look up information in any kind of a table, you're actually working with a two-dimensional data structure — a fancy term, but it just means table. If you want to look something up in a table, you need two indices, one to determine the row and another to determine the column.

If this concept is difficult to grasp, think of the old game Battleship. The playing field is a grid of squares. You announce I-5, meaning column I, row 5, and the opponent looks in that grid to discover that you've sunk his battleship. In programming, you typically use integers for both indices, but otherwise, it's exactly the same as Battleship. Any time you have two-dimensional data, you access it with two indices.

Often, we call the indices row and column to help you think of the structure as a table. Sometimes, other names more clearly describe how the behavior works. Take a look at Figure 4-7, and you see that the distance.html program asks for two cities and returns a distance according to the data table.

9781118289389-fg2107.tif

Figure 4-7: It's a Tale of Two Cities. You even get the distance between them!

technicalstuff.eps Yep, you can have three, four, or more dimension arrays in programming, but don't worry about that yet. (It may make your head explode.) Most of the time, one or two dimensions are all you need.

This program is a touch longer than some of the others, so I break it into parts in the following sections for easy digestion. Be sure to look at the program in its entirety on the website.

Setting up the arrays

The key to this program is the data organization. The first step is to set up two arrays.

<script type = "text/javascript">
//from distance.html

//cityName has the names of the cities
cityName = new Array("Indianapolis", "New York", "Tokyo", "London");

//create a 2-dimension array of distances
distance = new Array (
new Array (0, 648, 6476, 4000),
new Array (648, 0, 6760, 3470),
new Array (6476, 6760, 0, 5956),
new Array (4000, 3470, 5956, 0)
);

The first array is an ordinary single-dimension array of city names. I've been careful to always keep the cities in the same order, so whenever I refer to city 0, I'm talking about Indianapolis (my hometown), New York is always going to be at position 1, and so on.

warning.eps You have to be careful in your data design that you always keep things in the same order. Be sure to organize your data on paper before you type it into the computer, so you'll understand what value goes where.

The cityNames array has two jobs. First, it reminds me what order all the cities will be in, and, second, it gives me an easy way to get a city name when I know an index. For example, I know that cityName[2] will always be “Tokyo”.

The distance array is very interesting. If you squint at it a little bit, it looks a lot like Table 4-1, shown earlier in this chapter. That's because it is Table 4-1, just in a slightly different format.

distance is an array. JavaScript arrays can hold just about everything, including other arrays! That's what distance does. It holds an array of rows. Each element of the distance array is another (unnamed) array holding all the data for that row. If you want to extract information from the array, you need two pieces of information. First, you need the row. Then because the row is an array, you need the column number within that array. So, distance[1][3] means go to row 1 (“New York”) of distance. Within that row go to element 3 (“London”) and return the resulting value (3470). Cool, huh?

technicalstuff.eps A beginning programmer would typically solve this problem with a huge number of if statements. That solution will work, but it becomes unwieldy in a hurry. With four cities, you'll have four conditions to determine which city you're coming from, and each of these will need three conditions to determine where we're going. That's doable, but by the time you have ten cities, you'll have somewhere near one hundred conditions, and with one hundred cities, you'll have roughly ten thousand conditions. When you use an array like I'm demonstrating here, the code doesn't get more complex when the number of elements increases. For computer science majors out there, this problem has a complexity of Big O(n2), meaning as the number of elements increases, the complexity increases by the square. Using an array tames that complexity and makes the program much more efficient and extensible. Experienced programmers tend to aim for simpler code structure by using more complex data structures.

Getting a city

The program requires that you ask for two cities. You want the user to enter a city number, not a name, and you want to ask this question twice. Sounds like a good time for a function.

function getCity(){
// presents a list of cities and gets a number corresponding to
// the city name
var theCity = ""; //will hold the city number

var cityMenu = "Please choose a city by typing a number: \n";
cityMenu += "0) Indianapolis \n";
cityMenu += "1) New York \n";
cityMenu += "2) Tokyo \n";
cityMenu += "3) London \n";

theCity = prompt(cityMenu);
return theCity;
} // end getCity

The getCity() function prints a little menu of city choices and asks for some input. It then returns that input.

technicalstuff.eps You can improve getCity() in all kinds of ways. For one thing, maybe it should repeat until you get a valid number so that users can't type the city name or do something else crazy. I'll leave it simple for now. If you want to find out how user interface elements help the user submit only valid input, skip ahead to Chapter 5 of this minibook.

Creating a main() function

The main() function handles most of the code for the program.

function main(){
var output = "";
var from = getCity();
var to = getCity();
var result = distance[from][to];
output = "The distance from " + cityName[from];
output += " to " + cityName[to];
output += " is " + result + " miles.";
alert(output);
} // end main

main();

The main() function controls traffic. Here's what you do:

1. Create an output variable.

The point of this function is to create some text output describing the distance. I begin by creating a variable called output and setting its initial value to empty.

2. Get the city of origin.

Fortunately, you have a great function called getCity() that handles all the details of getting a city in the right format. Call this function and assign its value to the new variable from.

3. Get the destination city.

That getCity() function sure is handy. Use it again to get the city number you'll call to.

4. Get the distance.

Because you know two indices, and you know they're in the right format, you can simply look them up in the table. Look up distance[from][to] and store it in the variable result.

5. Output the response.

Use concatenation to build a suitable response string and send it to the user.

6. Get city names from the cityNames array.

The program uses numeric indices for the cities, but they don't mean anything to the user. Use the cityNames array to retrieve the two city names for the output.

7. Run the main()function.

Only one line of code doesn't appear in a function. That line calls the main() function and starts the whole thing.

tip.eps I didn't actually write the program in the order I showed it to you in the preceding steps. Sometimes it makes more sense to go “inside out.” I actually created the data structure first (as an ordinary table on paper) and then constructed the main() function. This approach made it obvious that I needed a getCity() function and gave me some clues about how getCity should work. (In other words, it should present a list of cities and prompt for a numerical input.)

Creating Your Own Objects

So far you've used a lot of wonderful objects in JavaScript, like the document object and the array object. However, that's just the beginning. It turns out you can build your own objects too, and these objects can be very powerful and flexible. Objects typically have two important components: properties and methods. A property is like a variable associated with an object. The properties taken together describe the object. A method is like a function associated with an object. The methods describe things the object can do. If functions allow you to put code segments together and arrays allow you to put variables together, objects allow you to put both code segments and variables (and functions and arrays) in the same large construct.

Building a basic object

JavaScript makes it trivially easy to build an object. Because a variable can contain any value, you can simply start treating a variable like an object and it becomes one.

Figure 4-8 shows a critter that has a property.

9781118289389-fg2108.tif

Figure 4-8: This alert box is actually using an object.

Take a look at the following code:

//from basicObject.html
//create the critter
var critter = new Object();

//add some properties
critter.name = "Milo";
critter.age = 5;

//view property values
alert("the critter's name is " + critter.name);

The way it works is not difficult to follow:

1. Create a new Object.

JavaScript has a built-in object called Object. Make a variable with the new Object() syntax, and you'll build yourself a shiny, new standard object.

2. Add properties to the object.

A property is a subvariable. It's nothing more than a variable attached to a specific object. When you assign a value to critter.name, for example, you're specifying that critter has a property called name and you're also giving it a starting value.

3. An object can have any number of properties.

Just keep adding properties. This allows you to group a number of variables into one larger object.

4. Each property can contain any type of data.

Unlike arrays where it's common for all the elements to contain exactly the same type of data, each property can have a different type.

5. Use the dot syntax to view or change a property.

If the critter object has a name property, you can use critter.name as a variable. Like other variables, you can change the value by assigning a new value to critter.name or you can read the content of the property.

technicalstuff.eps If you're used to a stricter object-oriented language, such as Java, you'll find JavaScript's easy-going attitude quite strange and maybe a bit sloppy. Other languages do have a lot more rules about how objects are made and used, but JavaScript's approach has its charms. Don't get too tied up in the differences. The way JavaScript handles objects is powerful and refreshing.

Adding methods to an object

Objects have other characteristics besides properties. They can also have methods. A method is simply a function attached to an object. To see what I'm talking about, take a look at this example:

//create the critter
//from addingMethods.html
var critter = new Object();

//add some properties
critter.name = "Milo";
critter.age = 5;

//create a method
critter.talk = function(){
msg = "Hi! My name is " + this.name;
msg += " and I'm " + this.age;
alert(msg);
} // end method

// call the talk method
critter.talk();

This example extends the critter object described in the last section. In addition to properties, the new critter has a talk() method. If a property describes a characteristic of an object, a method describes something the object can do. Figure 4-9 illustrates the critter showing off itstalk() method:

9781118289389-fg2109.tif

Figure 4-9: Now the critter can talk!

Here's how it works:

1. Build an object with whatever properties you need.

Begin by building an object and giving it some properties.

2. Define a method much like a property.

In fact, methods are properties in JavaScript, but don't worry too much about that; it'll make your head explode.

3. You can assign a prebuilt function to a method.

If you created a function that you want to use as a method, you can simply assign it.

4. You can also create an anonymous function.

More often, you'll want to create your method right there as you define the object. You can create a function immediately with the function(){ syntax.

5. The this keyword refers to the current object.

Inside the function, you may want to access the properties of the object. this.name refers to the name property of the current object.

6. You can then refer to the method directly.

After you define an object with a method, you can invoke it. For example, if the critter object has a talk method, use critter.talk() to invoke this method.

Building a reusable object

These objects are nice, but what if you want to build several objects with the same definition? JavaScript supports an idea called a constructor, which allows you to define an object pattern and reuse it.

Here's an example:

//building a constructor
//from constructor.html
function Critter(lName, lAge){
this.name = lName;
this.age = lAge;
this.talk = function(){
msg = "Hi! My name is " + this.name;
msg += " and I'm " + this.age;
alert(msg);
} // end talk method
} // end Critter class def

function main(){
//build two critters
critterA = new Critter("Alpha", 1);

critterB = new Critter("Beta", 2);
critterB.name = "Charlie";
critterB.age = 3;

//have 'em talk
critterA.talk();
critterB.talk();

} // end main
main();

This example involves creating a class (a pattern for generating objects) and reusing that definition to build two different critters. First, look over how the class definition works:

· Build an ordinary function: JavaScript classes are defined as extensions of a function. The function name will also be the class name. Note that the name of a class function normally begins with an uppercase letter. When a function is used in this way to describe an object, the function is called the object's constructor. The constructor can take parameters if you wish, but it normally does not return any values. In my particular example, I add parameters for name and age.

· Use this to define properties: Add any properties you want to include, including default values. Note that you can change the values of these later if you wish. Each property should begin with this and a period. If you want your object to have a color property, you'd say something like this.color = “blue”. My example uses the local parameters to define the properties. This is a very common practice because it's an easy way to preload important properties.

· Use this to define any methods you want: If you want your object to have methods, define them using the this operator followed by the function(){ keyword. You can add as many functions as you wish.

technicalstuff.eps The way JavaScript defines and uses objects is easy but a little nonstandard. Most other languages that support object-oriented programming (OOP) do it in a different way than the technique described here. Some would argue that JavaScript is not a true OOP language, as it doesn't support a feature called inheritance, but instead uses a feature called prototyping. The difference isn't all that critical because most uses of OOP in JavaScript are very simple objects like the ones described here. Just appreciate that this introduction to object-oriented programming is very cursory, but enough to get you started.

Using your shiny new objects

After you define a class, you can reuse it. Look again at the main function to see how I use my newly minted Critter class:

function main(){
//build two critters

critterA = new Critter("Alpha", 1);

critterB = new Critter("Beta", 2);
critterB.name = "Charlie";
critterB.age = 3;

//have 'em talk
critterA.talk();
critterB.talk();

} // end main
main();

After you define a class, you can use it as a new data type. This is a very powerful capability. Here's how it works:

· Be sure you have access to the class: A class isn't useful unless JavaScript knows about it. In this example, the class is defined within the code.

· Create an instance of the class with the new keyword: The new keyword means you want to make a particular critter based on the definition. Normally, you assign your new object to a variable. My constructor expects the name and age to be supplied, so it automatically creates a critter with the given name and age.

· Modify the class properties as you wish: You can change the values of any of the class properties. In my example, I change the name and age of the second critter just to show how it's done.

· Call class methods: Because the critter class has a talk() method, you can use it whenever you want the critter to talk.

Introducing JSON

JavaScript objects and arrays are incredibly flexible. In fact, they are so well known for their power and ease of use that a special data format called JavaScript Object Notation (JSON) has been adopted by many other languages.

JSON is mainly used as a way to store complex data (especially multidimensional arrays) and pass the data from program to program. JSON is essentially another way of describing complex data in a JavaScript object format. When you describe data in JSON, you generally do not need a constructor because the data is used to determine the structure of the class.

JSON data is becoming a very important part of web programming because it allows an easy mechanism for transporting data between programs and programming languages.

Storing data in JSON format

To see how JSON works, look at this simple code fragment:

var critter = {
"name": "George",
"age": 10
};

This code describes a critter. The critter has two properties, a name and an age. The critter looks much like an array, but rather than using a numeric index like most arrays, the critter has string values to serve as indices. It is in fact an object.

You can refer to the individual elements with a variation of array syntax, like this:

alert(critter["name"]);

You can also use what's called dot notation (as used in objects) like this:

alert(critter.age);

Both notations work the same way. Most of the built-in JavaScript objects use dot notation, but either is acceptable.

technicalstuff.eps The reason JavaScript arrays are so useful is that they are in fact objects. When you create an array in JavaScript, you are building an object with numeric property names. This is why you can use either array or object syntax for managing JSON object properties.

remember.eps Look at jsonDistance.html on the website to see the code from this section in action. I don't show a screenshot here because all the interesting work happens in the code.

To store data in JSON notation:

1. Create the variable.

You can use the var statement like you do any variable.

2. Contain the content within braces ( {}).

This is the same mechanism you use to create a preloaded array (as described earlier in this chapter).

3. Designate a key.

For the critter, I want the properties to be named “name” and “age” rather than numeric indices. For each property, I begin with the property name. The key can be a string or an integer.

4. Follow the key with a colon ( :).

5. Create the value associated with that key.

You can then associate any type of value you want with the key. In this case, I associate the value George with the key name.

6. Separate each name/value pair with a comma ( ,).

You can add as many name/value pairs as you wish.

technicalstuff.eps If you're familiar with other languages, you might think a JSON structure similar to a hash table or associative array. JavaScript does use JSON structures the way these other structures are used, but it isn't quite accurate to say JSON is either a hash or an associative array. It's simply an object. However, if you want to think of it as one of these things, I won't tell anybody.

Building a more complex JSON structure

JSON is convenient because it can be used to handle quite complex data structures. For example, look at the following (oddly familiar) data structure written in JSON format:

var distance = {
"Indianapolis" :
{ "Indianapolis": 0,
"New York": 648,
"Tokyo": 6476,
"London": 4000 },

"New York" :
{ "Indianapolis": 648,
"New York": 0,
"Tokyo": 6760,
"London": 3470 },

"Tokyo" :
{ "Indianapolis": 6476,
"New York": 6760,
"Tokyo": 0,
"London": 5956 },

"London" :
{ "Indianapolis": 4000,
"New York": 3470,
"Tokyo": 5956,
"London": 0 },
};

This data structure is another way of representing the distance data used to describe two-dimension arrays. This is another two-dimension array, but it is a little different than the one previously described.

· distance is a JSON object: The entire data structure is stored in a single variable. This variable is a JSON object with name/value pairs.

· The distance object has four keys: These correspond to the four rows of the original chart.

· The keys are city names: The original 2D array used numeric indices, which are convenient but a bit artificial. In the JSON structure, the indices are actual city names.

· The value of each entry is another JSON object: The value of a JSON element can be anything, including another JSON object. Very complex relationships can be summarized in a single variable.

· Each row is summarized as a JSON object: For example, the value associated with “Indianapolis” is a list of distances from Indianapolis to the various cities.

· The entire declaration is one “line” of code: Although it is placed on several lines in the editor (for clarity) the entire definition is really just one line of code.

Setting up the data in this way seems a bit tedious, but it's very easy to work with. The city names are used directly to extract data, so you can find the distance between two cities with array-like syntax:

alert(distance["Indianapolis"]["London"]);

If you prefer, you can use the dot syntax:

alert(distance.Indianapolis.Tokyo);

You can even go with some kind of hybrid:

alert(distance["London"].Tokyo);

JSON has a number of important advantages as a data format:

· Self-documenting: Even if you see the data structure on its own without any code around it, you can tell what it means.

· The use of strings as indices makes the code more readable: It's much easier to understand distance[“Indianapolis”][“London”] than distance[0][3].

· JSON data can be stored and transported as text: This turns out to have profound implications for web programming, especially in AJAX (the techniques described in Book VII).

· JSON can describe complex relationships: The example shown here is a simple two-dimension array, but the JSON format can be used to describe much more complex relationships including complete databases.

· Many languages support JSON format: Many web languages now offer direct support for JSON. The most important of these is PHP, which is frequently used with JavaScript in AJAX applications.

· JSON is more compact than XML: Another data format called XML is frequently used to transmit complex data. However, JSON is more compact and less “wordy” than XML.

· JavaScript can read JSON natively: Some kinds of data need to be translated before they can be used. As soon as your JavaScript program has access to JSON data, it can be used directly.

technicalstuff.eps You might wonder whether you can embed methods in JSON objects. The answer is yes, but this isn't usually done when you're using JSON to transport information. In Book VII about AJAX, you see that methods are often added to JSON objects to serve as callback functions, but that usage won't make sense until you learn more about events.