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.
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:
meaningOfLife
to that
location.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.
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?
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.
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.)
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.
+
, -
, *
,
/
, %
The operators defined on integer and floating-point numbers are
+
: addition-
: subtraction*
: multiplication/
: division, either integer or floating, as just
discussed%
: modulus, which gives the remainder of dividing two
numbers. 9 / 4 is 2 with a remainder of 1, so 9 % 4 equals 1.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:
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
.
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:
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.
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.
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.
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”.
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.
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.
!
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
.
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));
.
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 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.
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
.
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.
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.
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:
return
returns the value following return
(if any) to the calling code.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.
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.
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
.
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.