JavaScript Arrays

The construct that JavaScript uses to store lists of data items is the array. An array is a comma separated list of data items contained in a pair of square brackets. For example, here is a list of colors.

var colors = ['red','green','blue'];

To access individual elements in an array JavaScript uses a system of array indices. Each item in the array is numbered with an index value, with the index values starting at 0 and going up in steps of 1. For example, to access the first color in the list above we would use an index value of 0:

colors[0]

to access the last element in the list we would use an index value of 2:

colors[2]

JavaScript arrays come equipped with a length property that you can use to determine the length of the array. Since the index system is 0 based, the last index in a list is always equal to the length of the list minus one:

lastColor = colors[colors.length-1];

You can use the index notation both to read values from an array and to write values to the array. For example, to replace 'green' with 'yellow' in our list of colors we would do

colors[1] = 'yellow';

Automating Array Access with Loops

Here is another example of an array containing data values. The array in this example stores sales data for a restaurant over the six days in a week that the restaurant is open.

sales = [2302.50,2065.70,2290.85,2440.75,2804.25,3257.50];

Suppose now that we wanted to compute the total sales for the week. Here is one way to do this.

total = sales[0]+sales[1]+sales[2]+sales[3]+sales[4]+sales[5];

This works perfectly well, but does not scale well to larger problems. For example, if our list of sales data covered, say, 300 days worth of sales data writing out the sum over those 300 days would be very tedious.

Since arrays can potentially store large amounts of data, the key to working with lots of data is automation. JavaScript contains a number of language features that are useful for automating computational tasks. The first such mechanism we will encounter is the JavaScript loop.

To take advantage of JavaScript loops to automate the task of adding up the elements in an array I have to start by rewriting the example above slightly. Initially, this rewriting will make the example more verbose:

total = 0;
index = 0;
total = total + sales[index];
index = index + 1;
total = total + sales[index];
index = index + 1;
total = total + sales[index];
index = index + 1;
total = total + sales[index];
index = index + 1;
total = total + sales[index];
index = index + 1;
total = total + sales[index];

Not only is this form more verbose, it is also intentionally highly repetitive.

The next example makes use of a JavaScript while loop to automate the process of doing the repetitive steps in the last example:

total = 0;
index = 0;
while(index < sales.length) {
  total = total + sales[index];
  index = index + 1;
}

A while loop has the following structure

while(<test>) {
  <body statements>
}

The while loop is a repetition structure. On each repetition of the loop the <test> gets evaluated first. If the <test> evaluates to true, we will make one pass through the <body statements>. This process will repeat until the <test> evaluates to false.

Loops are most often used to systematically walk through the contents of an array. The key to doing this is to use an index variable to keep track of where we are in the array. Initially the index variable gets set to 0, which positions us at the first item of the list. On each pass through the loop body we use the index variable to access an item of data from the array and then we increment the index variable by 1 to move to the next location. This process continues as long as the index value is less than the length of the array. As soon as the index value is equal to the size of the array we have run off the end of the list and the loop test will terminate the repetition.

The advantage to using the loop structure is that it scales naturally to lists of any size. If our array of sales is 300 items long, the code above will still correctly compute the total of the items in the list.

Here is another example. Suppose we wanted to determine the highest value in the sales array. The following code does that.

highest = 0; // This is the highest we have seen
index = 0; // Start at the beginning of the array
while(index < sales.length) {
  if(sales[index] > highest) // If the current item beats highest
    highest = sales[index]; // record it as the new highest
  index = index + 1; // Go on to the next item
}

The for loop

JavaScript offers an alternative to the while loop. This alternative is motivated by the observation that almost every loop that seeks to walk across the contents of an array has a structure like this:

index = 0;
while(index < sales.length) {
  <do something with sales[index]>
  index = index + 1;
}

In every case we have to initialize the index variable to 0 at start, test whether or not it has run off the end of the array, and then increment the index at the end of the loop body. The for loop takes these common elements and simply rearranges them to form a more compact structure:

for(index = 0;index < sales.length;index=index+1) {
  <do something with sales[index]>
}

The general form for a for loop is

for(<initialization>;<test>;<increment>) {
  <body>
}

which does the same thing as the equivalent while structure that looks like

<initialization>
while(<test>) {
  <body>
  <increment>
}

In the interest of making the structure even more compact and easier to type, JavaScript allows you to use the shortcut form

index++

in place of the usual

index = index + 1

Cafe menu example

The example web page that goes with today's lecture uses loops and JQuery to construct a dynamic menu for an imaginary cafe.

The buttons at the bottom allow the user to select a meal. When the user clicks one of these buttons the table above the buttons will display the menu items that the cafe serves at that meal.

The data for the table entries is stored in a form of a JavaScript array containing a list of menu items. Each item is an object that describes that menu item, including what meal the item is served at.

var items = [{item:'Felafel sandwich',cost:'$4.50',meal:'L'},
             {item:'Cheese pizza',cost:'$4.50',meal:'L'},
             {item:'Breakfast Burrito',cost:'$3.50',meal:'B'},
             {item:'Hamburger',cost:'$4.00',meal:'L'},
             {item:'Mac and Cheese',cost:'$4.50',meal:'D'},
             {item:'Muffin',cost:'$2.50',meal:'B'},
             {item:'Salisbury Steak',cost:'$6.50',meal:'D'},
             {item:'Pancakes',cost:'$3.50',meal:'B'},
             {item:'Spaghetti',cost:'$4.50',meal:'D'}];

To obtain only the items served at a given meal, the program uses the following function:

function filterList(list,meal) {
  var result, n, length;

  result = []; // Make a new, empty list
  length = list.length;
  for(n = 0;n < length;n++) {
    // Search the original list for this meal's items
    if(list[n].meal == meal)
      result.push(list[n]); // Add matching items to the new list
  }

  return result;
}

The function takes the original array of menu items along with a meal code as its inputs and constructs a filtered array that contains only those items that are served at the given meal. The function constructs the new array by starting with an empty array. Each time the loop locates a new item of interest, we use the array push() method to push that item onto the new array.

Another application of loops in this example appears in the displayItems() function. This function takes a list of items to display and places them in the body of the table above the buttons. The code in this function uses the JQuery remove() and append() methods to remove existing rows from the table and add new rows to it.

function displayItems(items) {
  var table, newRow;
  var n, length;

  // Remove any existing entries from the table
  $('#menu tr').remove();

  // Add new rows for the items in the list
  length = items.length;
  for(n = 0;n < length;n++) {
    newRow = $('<tr>').html('<td>'+items[n].item+'</td><td>'+items[n].cost+'</td>');
    $('#menu').append(newRow);
  }
}

Another interesting piece of code here is the JQuery code to construct a new row for the table. The code starts with the JQuery expression

$('<tr>')

This application of the JQuery $() function is intended to create a new HTML element. Note the angle brackets in the parameter - these are only used when we want to make a new element. Once we have made the new element we immediately apply the JQuery html() method to it: this method places HTML content inside the new element. In this case the new element is a row for a table, and the new content is a couple of <td> elements written out in full HTML form.

Exercise calculator rewritten

As a second example I have rewritten the exercise calculator example from a previous lecture. I have made two specific changes: converting the DOM code to JQuery and replacing the original logic in the caloriesPerHour() function. Below is the new code for caloriesPerHour(), which takes advantage of our ability to use loops to fully separate the exercise calorie rate data from the logic of the function.

// Exercise data in the form of an array of objects
var data = [{activity:'walking',intensity:'low',calories:176},{activity:'walking',intensity:'medium',calories:232},
                {activity:'walking',intensity:'high',calories:352},{activity:'cycling',intensity:'low',calories:422},
          {activity:'cycling',intensity:'medium',calories:563},{activity:'cycling',intensity:'high',calories:704},
          {activity:'running',intensity:'low',calories:704},{activity:'running',intensity:'medium',calories:880},
          {activity:'running',intensity:'high',calories:1126},{activity:'swimming',intensity:'low',calories:422},
          {activity:'swimming',intensity:'medium',calories:563},{activity:'swimming',intensity:'high',calories:704}];

// A helper function to compute the calories per hour for
// an activity at a certain intensity
function caloriesPerHour(activity,intensity) {
  var n, length;

  length = data.length;
  for(n = 0;n < length;n++) {
    if(data[n].activity==activity && data[n].intensity==intensity)
      return data[n].calories;
  }

  return 0;
}