Variables, values, and expressions

This chapter discusses how to store data, how to compute values from data, and how to use changing values of data to affect program behavior.

Variables

It’s useful to be able to store values in the computer’s memory for later use. A variable is a name that refers to a location in the computer’s memory where a piece of information can be stored. A simple example:

The statement var meaningOfLife = 42; is called a variable assignment and it causes Javascript to do three things:

  1. Javascript reserves a space in memory to hold the integer value 42.
  2. Javascript gives the name meaningOfLife to that location.
  3. Javascript copies a pattern of 0s and 1s corresponding to the value 42 into that location in memory.

Later, when the value of the variable is needed (in the print(meaningOfLife); statement) the central processing unit of the computer (sometimes called the CPU) determines the location in memory with which the name meaningOfLife is associated, goes to that location, and fetches the value it finds there, making that value available to Javascript. Because this value is used in a print statement, Javascript prints the value 42.

This syntax should look familiar. Recall the syntax for defining a function:

var sayHello = function() {
    print( "I say hello." );
};

Both the variable and function definition follow the same pattern: the keyword var followed by a name, an equal sign, then either a value or the rest of the function definition, and finally a semicolon.

Using variables to change code behavior

We’ll see soon how to use variables to compute and store values. But one important use of variables is to change the behavior of code. First, we write the code in terms of some variables. Changing the values of those variables then changes the behavior of the code. The example below shows how this works. First, run the code. Then change the value of x to 60 and y to 120 and run the code again. How does the behavior of the program change?

Comments

In the previous example, there are several lines of code that include the symbols //, followed by some text in English. This text is a comment intended for human beings to read; the // indicates that the Javascript interpreter should ignore whatever text occurs afterwards on that line. The liberal use of helpful comments is a hallmark of an experienced coder, and code without comments should be considered bad code.

Comments explain code at a high-level in a way that is helpful when the code is modified or adapted, for either the original coder, or the next maintainer of the codebase.

Choosing good variable names

Variable names are sequences of letters, digits, and underscores. The first letter cannot be a digit, and variable names cannot contain spaces. Javascript is case-sensitive: uppercase and lowercase letters are considered to be different characters in variable names, so that the names meaningOfLife and Meaningoflife refer to different variables. You should choose variable names that are descriptive of the value that will be stored.

By convention, letters appearing in variable names in Javascript are mostly lowercase, and variable names start with a lowercase letter. If you want to make up a variable name from multiple words, use capital letters for each new word. (Some programmers call this “camel case”: meaningOfLife. Other languages, like Python, use underscores to separate words, but this is not the time to strike a bold blow for independence – you should follow Javascript conventions in your Javascript code.)

Expressions and operators

You can use Javascript to compute.

The plus sign is called an operator. An operator takes one or more operands, computes a result, and makes that result available to Javascript for further use. In this example, the operand on the left is 18, and the operand on the right is 24. An expression is an operator and its operands; we say that the expression can be evaluated to give a single value. In our example, the expression is 18 + 24; when evaluated, this expression’s value is 42, which we then assign to the variable sum. The second line of code then prints the value of this variable.

If we are only interested in printing the sum of 18 and 24 and not in storing the sum for future use, then we can combine the above two lines of code.

In this example, the parameter to print is an expression that is evaluated and the result of which is printed.

Similarly, an expression can be an operand to an operator:

print( (3 * 6) + 24 );

Here, the expression (3 * 6) is the left operand to the operator +.

The character * denotes multiplication in Javascript, to avoid confusion with the letter x. If Javascript needs the value of an expression, Javascript computes that value. In this example, the value of the expression (3 * 6) is needed before the addition can be done, and so the value 18 is computed first, by the multiplication operator *. That value, 18, can then be used as an operand to the addition operator.

Arithmetic operators such as +, -, *, and / (division) follow the same order of operations as you are used to from mathematics. * and / have higher precedence than + and -, meaning that they are evaluated first. Operators with the same precedence are evaluated left to right. Parentheses make the order of operations explicit. When in doubt, use parentheses to make your code as easy to read as possible.

For example:

The arithematic operators work for integers (… ,-2, -1, 0, 1, 2, …) and floating-point numbers (1.3, 2.5, 7.391, etc.). For example, if we divide two integers 5 and 2, Javascript will return a floating-point number.

Operators defined on the number type: +, -, *, /, %

The operators defined on integer and floating-point numbers are

The assignment operator ‘=’

The equals sign we saw earlier to assign a value to a variable is not the same as the equals sign you see in mathematics.

In mathematics, the equals sign is used to write down facts: the expression or variable on the left-hand side of the equation is now, and always will be, equal to the expression or variable on the right-hand side.

In mathematics, x = 5 is a fine equation. So is x = 6. But if I gave you both equations, you’d say I screwed up, because then x would equal both 5 and 6, and it just can’t. But in Javascript, the following works just fine:

Notice that we declared the variable x first, on a separate line, using the keyword var; this informs Javascript that x will be a variable. Declaring the variable reserves space in memory for values of that variable. Previously, we have combined decaration of the variable with setting the variables value into a single line of code.

The = operator in Javascript does not mean “mathematically equals.” In Javascript, the assignment operator, written with an equals sign, does two things:

  1. The expression on the right-hand side of the equals sign is evaluated.
  2. The computed value on the right-hand side is assigned (copied into) the space in memory assigned for the variable.

So the first line of code copies the value 5 into the variable x. The second line of code copies the value 6 into the variable x. When the program is finished, x has the value 6.

Here are a few statements that wouldn’t work in mathematics, but do work in Javascript:

In mathematics, x = x + 1 would mean something like “x is the number that is one greater than itself”. There is no such number.

In Javascript, there’s no problem. Evaluate the expression on the right-hand side. Fine—because x has the value 5, we know that x + 1 evaluates to 6. Assign that value to the variable on the left-hand side. Fine—now the variable x has the value 6.

When you see or write an equals sign in Javascript, do not think “mathematically equals.” Say in your mind, “assignment operator.” Compute the value on the right-hand side. Put the computed value into the variable on the left-hand side. That’s all.

Will the code 5 = x work in Javascript? No. The left-hand side operand of the assignment operator must be a variable name. 5 is not a variable name.

Have a look at the code below and predict what the output will be. Then run the code to verify your answers.

The first two lines assigns values of 1 and 2 to the variables x and y, respectively. The third line assigns to the variable z the sum of x and y, so z is assigned the value 3, which is then printed on line 4. On line 6, we assign the value of x to 2. When we print z, we see that z still has the value of 3. This is because z has the value 3, not x + y. The variable z knows nothing about the variables x and y or how it got the value 3 – so any changes to the variables x or y after z has been assigned has no impact on z.

Animations using variables

We’ve seen that the values of variables can be used to control the effect of code; in the example of the smiley face above, changing the values of x and y changes where the smiley is drawn on the screen.

A picture can be moved on the screen in the following way:

  1. Create some variables with some values
  2. Clear the screen
  3. Draw the picture on the screen using the values in the variables
  4. Change the values of the variables
  5. Go back to step 2

You know how to do most of this. To clear the screen, you can use the function call background(). The only thing you don’t know how to do is step 5. We’ll learn more about techniques to repeat code later, but for now we’ll use a simple trick. If you write a function draw(), then that function will be called repeatedly by the browser. (In general, this is not a good way to repeat most things. Use draw() only when you are building an animation.)

Let’s just see part of this first, without the drawing parts:

This code has three parts. First, the variables are created with initial values. Then the draw function is called. The browser will call draw over and over again. Within draw, we print the x value, and increase the value of x. Run the program and see what happens.

It’s important that the variables are defined outside of draw, since otherwise their values would be reset each time draw is called.

Exercise: moving smile

Objective: use a draw function that is called repeatedly by the browser, and some variables that change values, to animate a moving shape.

Write a program to draw a smile that moves from left to right across the screen. (Feel free to copy in whatever code you need from previous examples, including the one where the smile is drawn.)

Here is a solution.

The string type

As we saw in the first lecture, there are many different types of data to store. Numbers are one type; letters of the alphabet are another. The string type of data represents one or more letters of the alphabet, symbols (such as @ or ~), or digits.

When you type a string value into Javascript, it must be surrounded by quotes, so that the string does not look like the name of a variable.

var lastLetter = "Z";
print( lastLetter );

We call "Z" a string literal, since it should be interpreted by Javascript literally as the character “Z” and not as some variable name or anything else. (In x = 42, the number 42 is an integer literal.)

print( "hello" );

The quotes say that "hello" is a string, and not a variable name. More examples:

The quotes just identify the data as a string; the quotes aren’t part of the string.

Javascript is unusual in that you can use either single quotes or double quotes around the string, as long as you use the same kind of quotes before and after a given string. So the following lines do the same thing:

print( "hello" );
print( 'hello' );

But print( "hello' ); would be an error.

String concatenation

The plus sign, +, behaves differently depending on the types of the data that are on either side of it. If there are integers on either side, the plus sign is the integer-addition operator, and it adds the two integers to get another integer. If there are floating-point numbers on each side, they are added to get another floating-point number.

print( 3 + 4 );                // prints 7
print( 3.1 + .041592654 );     // prints 3.141592654

What if there are strings on each side? Then the plus sign is the string-concatenation operator. Concatenation means to “combine two strings together”.

Converting between types

There are a few special functions that convert between types of data: Number and String are useful for the types of data we’ve seen so far.

The function type

A function is itself a data type in Javascript. You can think of the name of the function as a variable that contains the address of the function’s lines of code. What this means is that other variables can also store a reference to the function. Here is an example:

Notice that the keyword function creates a new function in the function header var sayHello = function() {. A reference to this new function is then stored in the variable sayHello. Later, the value of the variable sayHello, which is a reference to the function, is copied into the variable s. Now both variables sayHello and s contain references to the same function.

The boolean type and the negation operator: !

There’s one more basic type of data, which we’ll use in the next lecture, called a boolean. There are only two possible values: true and false.

There is an operator that computes the opposite of a boolean value, !. So the value of the expression !true is false, and the value of the expression !false is true.

Function calls are expressions, too

When a function is called, the program counter jumps to the first line of the function body, some lines of code are executed, and then the program counter returns back to the point of call. During the process of running those lines of code, a value might be computed and made available.

An expression is anything that computes a value and makes it available. If you wanted to print the square of the number 3, you could write print(9), or your could write print(3 * 3); the expression 3 * 3 computes the number 9 and makes it available for further use. What if you wanted to print the square root of 25? You could write print(5). Or you could write print(Math.sqrt(25)); The function call Math.sqrt() is itself an expression that computes a value and makes it available. (For now, think of the period in the function name as just part of the function name. We’ll see later that it has a special meaning.)

You can use an expression anywhere a value is needed. For example, you could store the results of computing an expression in a variable x = Math.sqrt(25), use the results as part of another expression x = 4 + Math.sqrt(25), or use the results as a parameter to another function call print(Math.sqrt(25));.

Functions that return random values

The Math object has other built-in functions that return values. Math.random() returns a random number between 0 and 1.

Notice that to ensure that we got the same random color when drawing the outline of the face and the arc for the mouth, we saved the random values we first computed in variables r, g, and b, rather than calling random again later.

Functions: parameters, return values, scope

Functions are the primary way of organizing code into small, testable units.

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.

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.

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.