A function is a block of JavaScript that robotically does the same thing
again and again,
whenever you invoke its name. It saves you repetitive coding and makes
your code easier to
understand.
On your website, suppose there are several pages where you want to
display an alert that
tells the user the current time. (To keep it simple, we'll settle for
24-hour time rather than
converting to a.m. and p.m.) The code might look like this.
1 var now = new Date();
2 var theHr = now.getHours();
3 var theMin = now.getMinutes();
4 alert("time: " + theHr + ":" + theMin);
You could write this block of code over and over again, every time you
need it. Or you
could write it once as a function, naming it, say, tellTime. After that,
this is the only code
you'll need in order to make the whole block execute:
tellTime();
Whenever JavaScript sees that short statement, the time-telling block
executes.
This is how you package the one-off code above as a repeatable function:
1 function tellTime() {
2 var now = new Date();
3 var theHr = now.getHours();
4 var theMin = now.getMinutes();
5 alert("Current time: "+ theHr + ":" + theMin);
6 }
The time-telling code—the code that creates the Date object, extracts
the time, formats it,
and displays an alert—is exactly the same code we started with, but is
now packaged as a
function. Here are the parts:
1. On line 1 an opening declaration statement that includes:
• the keyword function
• a name I made up for the function
• parentheses that identify it as a function
• an opening curly bracket to enclose the code that will execute
2. On lines 2 through 5 the same block of code that you saw before
executes, but it's
indented for clarity. Opinions vary on how much to indent. I train you
to indent 2 spaces.
3. On line 6 a closing curly bracket on its own line to enclose the code
that will execute
Again, note that the calling code—the code that invokes the
function—does nothing more
than state the name of the function including its parentheses.
tellTime();
You can give a function any name that would be a legal variable name,
then add
parentheses. Function-naming follows the same rules as variable naming
because, technically,
a function is a variable. This will make more sense to you when you
learn more about
functions in a subsequent chapter.
Functions and the statements that call them may be separated by
thousands of lines of
code. Typically, functions are in the same place as the main code—in an
external JavaScript
file, at the end of the HTML body section, or in the HTML head section.
Normally, all the
functions should precede the main code, so when they're called by the
main code, they're
already loaded in memory and ready to go.
A function is a block of code that does something robotically, whenever
you invoke its
name. For example, when you write greetUser(); a function with that name
executes. To be
clear: The kind of function I'm talking about is one that you've written
yourself, and named
yourself.
Suppose that when you write greetUser(); a function is called that
displays an alert
saying, "Hello, there."
This is the code for the function.
1 function greetUser() {
2 alert("Hello, there.");
3 }
One of the really useful things about functions is that those
parentheses in the calling code
don't have to be empty. If you put some data inside the parentheses, you
can pass that data to
the function that it'll use when it executes.
Suppose, instead of writing greetUser(); you write...
greetUser("Hello, there.");
Now, instead of just calling the function, you're calling it and passing
data to it. The
string inside the parentheses, i.e. the data you're passing, is called
an argument.
The function is now more versatile, because the message it displays is
no longer hardwired into
it. It'll display any message that you pass to it from the calling code,
via the
argument.
In order for a function to become a programmable robot rather than a
one-job robot, you
have to set it up to receive the data you're passing. Here's how you do
it.
1 function greetUser(greeting) {
2 alert(greeting);
3 }
So now we've filled the parentheses of both the calling code and the
function definition.
The parentheses of the calling code contain an argument. In the example,
the argument is the
string "Hello, there." And, as you can see in the example above, the
parentheses of the function
definition now contain a variable, greeting.
A variable inside the parentheses in a function statement is known as a
parameter. The
parameter name is up to you. You can give it any name that would be
legal for a variable. Then
you can use it to accomplish something in the body of the function. On
line 2 in the example
above, I used it to specify the message in an alert.
You don't have to declare a variable when it's used as a parameter in a
function
definition. When it's used as a parameter, the declaration is implicit.
The argument in the statement that calls the function —"Hello,
there."—is the data that's
passed to the function. The parameter inside the parentheses in the
function definition catches
the data that's passed. It now holds "Hello, there." In other words, the
string "Hello, there",
specified in the function call, is assigned to greeting in the function.
Then that variable,
greeting, is used to specify the message in the alert statement.
The value passed to a function is used in the body of the function to
accomplish
something. In this case, the value is used to specify the message in the
alert.
In the example, the argument is a string, but it could just as easily be
a variable. In the
following code, I declare the variable greeting and assign it the value
"Hello, there." Then,
rather than using the string itself as an argument in the function call,
I use the variable.
1 var greeting = "Hello, there."
2 greetUser(greeting);
In the example above, the name of the function greetUser, shares some of
its name with
the parameter greeting, but that's just to make the code easy to
understand. The name of the
function and the name of the parameter don't have to have anything in
common. And remember,
these names are up to you, as long as you follow the variable-naming
rules.
In the example, I named the argument in the calling code greeting, and
also named the
parameter in the function code greeting. But this isn't necessary,
either. They don't have to
match. No matter what an argument's name is, it is accepted by the
parameter, no matter what
the parameter's name is. In the following code, the variable whatever is
the argument. The
parameter greeting doesn't match the name, but still catches the value.
Here's the function, once again, with the parameter greeting.
1 function greetUser(greeting) {
2 alert(greeting);
3 }
And here's the statement that calls the function, with the argument
whatever.
1 var whatever = "Hello, there.";
2 greetUser(whatever);
It's okay that the name of the argument and the name of the parameter
don't match. The
parameter still catches the argument, the string "Hello, there."
Still, it often makes sense to give an argument and a parameter the same
name, for clarity.
A number, either a literal number or a number represented by a variable,
can be an
argument. In the following code I declare the variable almostAMil and
assign the number
999999 to it. Then I use almostAMil as the argument in the function
call.
1 var almostAMil = 999999;
2 showBigNum(almostAMil);
Alternatively, if I wanted to, I could use the literal number 999999 as
the argument.
showBigNum(999999);
You can pass any number of arguments, separated by commas, to a
function. Typically,
the function has the same number of parameters, also separated by
commas. (There are rare
exceptions for special cases.) Again, when you use variables as
arguments, their names don't
have to match the names of the parameters. JavaScript matches up
arguments and parameters
according to their order, not their names. The first argument in the
list is passed to the first
parameter in the list, the second argument is passed to the second
parameter, and so on.
As arguments, you can use any combination of variables, strings, and
literal numbers. In
the following example, the calling code passes a variable, a string, and
a number to the
function. Three parameters catch the values. The function concatenates
them to create an alert
message.
First, here's the function.
1 function showMessage(m, string, num);
2 alert(m + string + num);
3 }
Now here's the statement that calls the function.
1 var month = "March";
2 showMessage(month, "'s winner number is ", 23);
The argument, month, a variable, is passed to the parameter m. The
argument "'s winning
number is ", a string, is passed to the parameter string. The argument
23, a literal number, is
passed to the parameter num.
When the code executes, an alert displays saying, "March's winning
number is 23."
Normally, you'd use all the parameters included in the function
definition as variables in
the code that executes, because, why else would you want them in the
function definition? But
there's nothing that says you must use them all. And you certainly don't
have to use them in the
same order in which they appear within the parentheses. Each one is a
full-fledged variable
that, within the function, you can use the way you'd use any variable.
As you learned in the last chapter, a function becomes more versatile
when you pass data
to it so it can deliver a custom job.
But a function can do even more. It can pass data back to the calling
code.
Let's say you charge a minimum shipping rate of $5, plus 3 percent of
the merchandise
total above $50, up to $100. You offer free shipping when the total hits
$100. Here's the code
that calculates the order total.
1 var orderTot;
2 if (merchTot >= 100) {
3 orderTot = merchTot;
4 }
5 else if (merchTot < 50.01) {
6 orderTot = merchTot + 5;
7 }
8 else {
9 orderTot = merchTot + 5 + (.03 * (merchTot - 50));
10 }
If the merchandise total is at least $100 (line 2), the order total is
the same as the
merchandise total (line 3). If the merchandise total is $50 or less
(line 5), the order total is the
merchandise total plus $5 (line 6). If the order total is between $50
and $100 (line 8), the
order total is the merchandise total plus $5 plus 3 percent of the
amount over $50 (line 9).
Something costing $150 is $150 total.
Something costing $15 is $20 total.
Something costing $70 is $75.60 total.
Here's how we turn the code above into a function.
1 function calcTot(merchTot) {
2 var orderTot;
3 if (merchTot >= 100) {
4 orderTot = merchTot;
5 }
6 else if (merchTot < 50.01) {
7 orderTot = merchTot + 5;
8 }
9 else {
10 orderTot = merchTot + 5 + (.03 * (merchTot - 50));
11 }
12 return orderTot;
13 }
The thing to focus on here is that we declare a variable, orderTot (line
2), and then—
here's what's new—after the processing is done and the merchandise total
is known, the
function returns the value held in orderTot to the calling code (line
12). It passes data back.
But then the calling code needs something to catch the data. What else
could this
something be but a variable? Here's the code that calls the function.
var totalToCharge = calcTot(79.99);
If you're new to coding, this statement may look odd to you. How can a
function be
assigned to a variable? You may be used to seeing a literal value
assigned to a variable....
var totalToCharge = 85.00;
You may be used to seeing a variable assigned to a variable...
var totalToCharge = merchTotal;
And you may be used to seeing an arithmetic or other expression assigned
to a variable...
var totalToCharge = merchTotal + ship + tax;
But assigning a function to a variable?
Well, it's not really that odd, because, remember, what you're actually
assigning to the
variable is the value passed back by the return statement in the
function code. The
statement...
var totalToCharge = calcTot(79.99);
...is shorthand for: "Assign to the variable totalToCharge the value
returned by the
function calcTot."
So now there's two-way communication between the calling code and the
function. The
calling code passes the value 79.99 to the function, which is caught by
the function's parameter
merchTot. This variable, merchTot, is used in the body of the function
to calculate an order
total. Then, through the return statement, that order total is passed
back to totalToCharge in
the calling code. It's a complete circle.
Notice that the variable in the calling code, totalToCharge, that
catches the value is
different from the variable inside the function, merchTot, that returns
the value. I did this
purposely, so you wouldn't think the two variables have to share the
same name. In the last
chapter you learned that when an argument in the calling code passes a
value to a parameter in
the function definition, they can have the same name, but don't have to.
The same applies to the
variable that's returned from a function and the variable in the calling
code that catches it. They
can share the same name, but don't have to.
Anywhere you can use a variable, you can use a function. (Technically, a
function is a
variable.) For example...
You can use a function to specify the message in an alert.
alert(calcTot(79.99));
In the example above, the alert message is the value returned by the
function calcTot
when the function is passed 79.99 as a parameter.
You can use a function in an expression.
var orderTot = merchTot + calcTax(merchTot);
In the example above, the value assigned to orderTot is the sum of
merchTot and the
value returned by the function calcTax when the function is passed
merchTot as an argument.
You can use a function in a function call.
var tot = calc(merchTot, calcTax(merchTot));
In the example above, the calling code passes two arguments to the
function calc. The
first argument is merchTot. The second argument is the function calcTax,
which is also
passed merchTot.
Within a function, you can call another function.
1 function calcTot(price) {
2 return price + calcShip(price);
3 }
In the example above, the function calcTot calls the function calcShip.
It passes price
as an argument and receives the shipping charge back. It adds the
shipping charge to the price,
and returns the sum to the original calling code as a total.
You've learned that you can pass any number of arguments to any number
of parameters.
Unfortunately, you don't have this flexibility in the return statement.
No matter how many
parameters it takes or how much processing it does, a function can
return only a single value to
the code that calls it.
Now we come to the subject of variable scope. That is, the difference
between global
and local variables. Some variables have global scope, which makes them
global variables.
Other variables have local scope, which makes them local variables.
Nothing could be
simpler, but for some reason, when the subject comes up in books and
tutorials, obfuscation
often rules. Relax. This will be easy.
A global variable is one that's declared in the main body of your
code—that is, not inside
a function.
A local variable is one that's declared inside a function. It can be
either a parameter of
the function, which is declared implicitly by being named as a
parameter, or a variable
declared explicitly in the function with the var keyword.
What makes a global variable global is that it is meaningful in every
section of your code,
whether that code is in the main body or in any of the functions. Global
scope is like globa
l fame. Wherever you go in the world, they've
heard of Bill Clinton.
A local variable is one that's meaningful only within the function that
declares it. Local
scope is like local fame. The mayor of Duluth is known within Duluth,
but pretty much
unknown everywhere else.
So there are two differences between global and local variables—where
they're
declared, and where they're known and can be used.
Before I show you the first example, I want you to set aside what you
know about passing
values to a function through arguments, and passing a value back to the
calling code by way of
the return statement. Pretend you don't know anything about these
things. I'll come back to
them later. Here's an example.
First, in the main code, a variable declaration followed by a call to a
function:
1 var theSum
2 addNumbers();
Then the function:
1 function addNumbers() {
2 theSum = 2 + 2;
3 }
In the example, the variable theSum is declared in the main code. The
function
addNumbers is called to assign it a value. Having been declared in the
main code, the variable
has global scope, so this function or any other function can use it. So
can anything in the main
code. The function assigns the sum of 2 + 2 to this global variable.
Since the variable has
global scope, the assignment is meaningful in all sections of your code,
both the main code and
in all functions. The variable now has the value 4 in the function
addNumbers, in the main
code, and in any other functions that use it. It doesn't matter where I
write...
alert(theSum);
Wherever I write it—in the main code, in the function addNumbers, or in
any other
function, an alert will display the number 4.
But if I declare the variable not in the main code, but inside the
function...
1 function addNumbers() {
2 var theSum = 2 + 2;
3 }
...the variable has the value 4 only inside the function. Everywhere
else, it's unknown.
Everywhere else, it has no value at all. Since the variable theSum is
declared with the
keyword var inside the function, not in the main code, its scope is
local. It is meaningful only
inside the function. In other functions and in the main code, it is
unknown. If I write...
alert(theSum);
...in the function, an alert displays the number 4, because the variable
theSum is known
inside the function, where it was declared. But if I write the same
alert statement anywhere
else—in the main code or in another function—the code breaks, because
theSum is unknown
outside the function.
Note: I say that a variable has local scope when you declare it in a
function. By
"declaring it in a function" I mean that you declare the variable
explicitly with the keyword
var—as opposed to casually introducing it into the function without var.
(The exception is if
you name it as a parameter, in which case it's declared implicitly as a
local variable of the
function.) If you get sloppy and begin using a new variable in the body
of a function without
explicitly declaring it in the function with the keyword var, it is
global—even though you
haven't declared it anywhere in the main code.
Now, to illustrate a point, I'm going to do something you'd actually
never want to do in
your code. I'm going to declare a variable both in the main code and in
the function.
First, in the main code:
1 var theSum = 1000;
2 addNumbers();
Then in the function:
1 function addNumbers() {
2 var theSum = 2 + 2;
3 }
By declaring the variable twice—once in the main code and again in the
function—I've
created two different variables that share the same name. One theSum is
global. The other
theSum is local. This is not something you would ever want to do—it sets
you up for coding
mistakes and makes your code almost impossible to follow—but I did it to
show the difference
between global and local scope. By declaring theSum once in the main
code, and again in the
function, I've created (1) a global variable that's useable almost
everywhere and (2) a local
variable of the same name that's useable only inside the function. Why
do I say the global
variable is useable almost everywhere? Because it's no good inside the
function. Inside the
function, the name theSum stands for a local variable, so the name can't
refer to the global
variable. In this situation, coders say the global variable is in the
shadow of the local
variable. Inside the function, it can't be seen. Inside the function,
only the local variable of that
name can be seen.
The local variable theSum has a value of 4 inside the function, but
theSum outside the
function has a value of 1000.
Now let's journey a little farther into Wonderland, Alice.
First, a statement in the main code:
1 var theSum = addNumbers();
Then a function:
1 function addNumbers() {
2 var theSum = 2 + 2;
3 return theSum;
4 }
Again, this isn't something you'd actually code. I use the example only
to demonstrate
principles. In this code, you still have two different variables—a
global variable and a local
variable—that share the same name, theSum, but now, thanks to the return
statement, the
value of the local variable is assigned to the global variable. Now both
variables have the
same name and the same value, but they're still different variables.
Which brings us to a question you may be asking:
If a function can use a global variable, why do you have to pass a value
from an argument
to a parameter? Why not just declare a global variable, then have the
function use it? Well, you
can, but asking functions to work with global variables is asking them
to eavesdrop on the
main code, and like human eavesdropping, it invites mischief in the form
of confusion and
unintended consequences. There is no controversy among coders about
this. It's always best to
pass values explicitly to functions through arguments. Global variables
have no place in
functions.
The same logic applies to the the argument for using the return
statement. You can
change the value of a global variable within a function. When you do,
the value of it changes
everywhere, including in the main code. No return is needed. But it's
better practice to usea
local variable within the function, then pass that value back explicitly
through a return
statement.