Handling data: Arrays and functions

The array type

So far, we’ve needed a new variable name for each new piece of information we wanted to store. Now we will see how to store and manipulate larger groups of data, organized by Javascript in data structures.

An array is a data structure that can store multiple pieces of information, in order, and with a single variable name. There are two main uses of array:

  1. Storing large amounts of similar data using just one name for the array.
  2. Applying similar operations to many pieces of data.

The array name, together with a non-negative integer can be used to refer to the individual items of data. Let’s start with an example:

The variable cars is an array containing five strings. The array is defined like any other variable, except that we use square brackets [] to denote an array and separate the elements of an array with commas.

We can access individual items of the list by indexing into the list with squares brackets and an intger value:

Note that the first element of the list corresponds to index 0 and so a list with 5 elements will have valid indices of 0, 1, 2, 3, and 4.

We can also print the entire array just like any other variable:

The items of an array can be treated as variables. You can use the assignment operator to change an item in a array.

If you forget that the list is indexed from 0, or for some other reason try to access an item of the array at an index beyond the end of the list, Javascript will print an error message.

To help avoid this error, you can find out how many items are in an array.

This dot-notation (schools.length) is new. We’ll tell you how it works and why in the next few sections.

Loops and arrays

A array is a way of organizing, or structuring, data that your program will use. We say that an array is a data structure, and we will see many other examples of data structures later in the course. One of the key principles of a data structure is that the data structure allows you to apply operations to some or all of the data in a unified way.

Let’s take an example. You decide to start a new financial data aggregation website. Initially, daily currency are recorded in US Dollars.

var apple = [101.42, 96.30, 96.79, 96.66, 97.13, 99.52, 97.39];

But then next year, based on uncertain politics in the United States, the world decides to move to the Euro as the world’s primary currency. You decide to convert all of your currency data from US Dollars to Euros (and move to Canada). You could convert all of your data this way:

You are doing the same type of operation over and over again. Convert apple[0]. Convert apple[1]. Convert apple[2]. And so on. This is tedious with only six data points. Imagine how tedious it would be with millions of data points. There is a simpler way to apply the same operation to all elements of an array.

Let’s look more closely at this for-loop. The for-loop consists of a header and a body. The header initializes the counter variable i, and increments the counter variable as long as i is less than the length of the array. We’ll use i to index into the array for each conversion we need to do.

The body of the for-loop contains whatever code we want to execute on each iteration of the for-loop. In our example, this is a single line of code that converts the ith element of the array from dollars to Euros:

apple[i] = apple[i] * rate;

Like a function, the body of the for-loop is enclosed between an open and closed curly brackets {}.

Exercise: falling star

Here is a solution.

Functions: parameters, return values, and scope

Some functions need to have information in order to do their jobs. Some functions compute some value that they need to make available once they’re finished. And many functions need to create variables that are used only temporarily, while the function is being executed.

Passing parameters to functions

One way to get information into a function is through parameters. We have already seen several examples of calling functions that take parameters. Here’s one:

The ellipse function requires four parameters, in order: the x and y locations of the center of the ellipse, and the width and height of the ellipse.

Now let’s see how to define functions that take parameters.

You put the parameters between the parentheses in the function’s header. Each parameter is actually a special variable. We call a parameter that appears in a function’s header a formal parameter. If a function takes more than one formal parameter, we separate them by commas in the function’s header.

Here is an example of a program that contains a function to draw the outline of a square:

The formal parameters are variables named x, y, and s. When square is called, the first value in the function call, 10, is copied into the first formal parameter in the function header, x. The second value in the function call, 20, is copied into the second formal parameter in the function header, y. The third value in the function call, 80, is copied into the third formal parameter, s.

After Javascript has copied these three values into the formal parameters, it sets the program counter to the first line of the body of square. At this point, there are three variables available: x, y, and s.

We call the numbers 10, 20, 80 that are actually passed into the function actual parameters. When a function is called, the values of the actual parameters are computed and copied into the formal parameters. The actual parameters are values (or expressions) in the function call instruction, and the formal parameters are the variables used in the function itself. An actual parameter can be a complicated expression. What matters is the value that it evaluates to.

The values of the actual parameters are copied into the corresponding formal parameters, position by position, left to right.

In our example, because 10 is the first actual parameter, its value is copied into the first formal parameter, x. Because 20 is the second actual parameter, its value is copied into the second formal parameter, y. And because 80 is the third actual parameter, its value is copied into the third formal parameter, s.

Exercise: tree

Objective: Wrap code into a function that takes parameters.

Here is some code to draw a simple tree. Write a function drawTree that allows a tree to be drawn so that the bottom center of the tree is positioned at x and y coordinates specified as function parameters. To test your code, call the function a few times, to draw trees that sit on the bottom of the screen.

Exercise: forest

Objective: Call a function in a loop, with randomly generated parameters.

Write a for loop that calls the drawTree function 10 times, placing each trees with its base on the bottom of the screen, but at a random horizontal location (x coordinate). (Remove the three sample trees.)

Some functions return values

Expressions compute values and make those values available for further use. Functions can also compute values and make those values available for further use. They don’t have to do that, but they can. For example, the sqrt function returns a value, which is the square root of the value of the actual parameter passed to it. When a function computes a value that is available for further use, we say that the function returns the value.

Anywhere a value is needed, a call of a function that returns the right type of value (for example, a string, a number, or a boolean) can appear.

For example, the function Math.sqrt(x) computes the square root of x, and returns the computed value. We can use Math.sqrt(x) in a variable assignment, as a parameter to a function call, in header of a for loop, or anywhere else a value is needed:

It’s good enough to think of Math.sqrt as the name of the function, but if you’ve noticed the dot in the function name, think about how objects work. Math is actually a reference to an object that contains a reference to the function sqrt; you can think of sqrt as being inside the Math object.

Defining your own functions with return values

When the value returned by a function is needed, the function is called. The current value of the program counter is saved. Then the program counter is set to the first line of the function. Javascript executes the body of the function. The function returns and the program counter is set to its value before the function call when one of two things happens:

Executing a return-statement does two things:

  1. return returns the value following return (if any) to the calling code.
  2. return immediately stops execution of the body of the function and resumes execution at the point of call. That is, the program counter goes back to just after the function was called.

Here’s a really simple example:

Do not confuse print and return. The print statement causes text to appear on the screen in order to communicate with a human being; the return statement communicates values between separate modules of code.

Here’s one more example.

The line print("I computed the value!"); is not executed and the string is not printed on the screen, since the return statement before the print statement will always immediately give control back to the calling function by setting the value of the program counter. In fact, Javascript will warn you that you have done something silly. Lines of code that cannot be reached are called dead code. Normally, you should not include dead code in a program.

Exercise. Write a function circleArea7 that computes the area of a circle of radius 7, and returns that area. Call the function and print the result to verify that it works.

Exercise. Write a function circleArea that takes a parameter radius, and computes the area o a circle with that radius. Call the function three times, to compute the areas of circles of size 3, 5, and 7, and print the results.

Exercise: prime

Objective: Wrap code inside a function that returns a value (factoring).

Here is some code to test if an integer greater than 1 is prime. Using this code as a starting point, write a function that takes a number as input, and returns false if that number is not prime, and true otherwise.

Exercise: primes

Objective: Make use of a function that you have written to compute several values.

Here is a function to test if a number is prime. Write a loop that prints the prime numbers between 2 and 100.

Local variables and scope

Variables in Javascript are either local to a single function or global and accessible by any function. Javascript has some particular rules that determine whether a variable is local or global and how you access the variable.

Local variables

When you declare a variable inside a function, that variable is a local variable. A local variable is not accessible by any code outside the function in which it is defined. A local variables exists during that call of the function, and then it ceases to exist. You can think of local variables a disposable—use them in the function, and throw them away. Almost all of the variables you declare in this course will be local variables.

Here is an example:

The line print(x) inside the function definition works just fine. But the line print(x) after the call to someFunction is an error. That’s because x is initialized with the keyword var within someFunction, and so x is local to someFunction. Therefore, x is not known outside someFunction.

Scope

Every now and then, you want a variable to be available to many functions. When a new function is created, it creates its own little workspace where it can store temporary variables. We call this workspace the scope of the function. We say that code outside of any functions is in the global scope.

In the previous example, var x = 4; was defined within the body of the someFunction function, so the variable x was placed in the scope of someFunction.

Scopes can contain other scopes, and code can see any variables defined either within the current scope, or within some containing scope. For example, the global scope contains all of the other scopes, so the following code works:

Here, the function printX accesses the variable x, since x is in a scope that contains the scope of printX.

Because x has the value 5 when the function is called, the assignment statement within the function assigns the value 6 to x, and both print statements print the value 6.

Functions can actually be defined within other functions in Javascript. Each new function creates a scope that is inside the scope of the outer, or containing, function. The inner function can access the variables of the outer function, if those variables were initialized before the inner function was called. However, the outer function cannot access variables initialized within the inner function.

Notice that we define functions and store references to them in variables. So the variable innerFunction is not available at the global scope, and cannot be called except within the body of outerFunction.