Functions: Function Declaration
Functions: Function Declaration
Functions: Function Declaration
Quite often we need to perform a similar action in many places of the script.
For example, we need to show a nice-looking message when a visitor logs in, logs out and
maybe somewhere else.
Functions are the main “building blocks” of the program. They allow the code to be called
many times without repetition.
Function Declaration
To create a function we can use a function declaration.
function showMessage() {
alert( 'Hello everyone!' );
}
The function keyword goes first, then goes the name of the function, then a list
of parameters between the parentheses (comma-separated, empty in the example above) and
finally the code of the function, also named “the function body”, between curly braces.
function name(parameters) {
...body...
}
Our new function can be called by its name: showMessage().
For instance:
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage();
showMessage();
The call showMessage() executes the code of the function. Here we will see the message two
times.
This example clearly demonstrates one of the main purposes of functions: to avoid code
duplication.
If we ever need to change the message or the way it is shown, it’s enough to modify the code
in one place: the function which outputs it.
Local variables
A variable declared inside a function is only visible inside that function.
For example:
function showMessage() {
let message = "Hello, I'm JavaScript!"; // local variable
alert( message );
}
Outer variables
A function can access an outer variable as well, for example:
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
For instance:
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) changed the outer variable
showMessage();
If a same-named variable is declared inside the function then it shadows the outer one. For
instance, in the code below the function uses the local userName. The outer one is ignored:
let userName = 'John';
function showMessage() {
let userName = "Bob"; // declare a local variable
alert( userName ); // John, unchanged, the function did not access the outer
variable
Global variables
Variables declared outside of any function, such as the outer userName in the code above, are
called global.
Global variables are visible from any function (unless shadowed by locals).
It’s a good practice to minimize the use of global variables. Modern code has few or no globals.
Most variables reside in their functions. Sometimes though, they can be useful to store project-
level data.
Parameters
We can pass arbitrary data to functions using parameters (also called function arguments) .
In the example below, the function has two parameters: from and text.
Here’s one more example: we have a variable from and pass it to the function. Please note: the
function changes from, but the change is not seen outside, because a function always gets a
copy of the value:
// the value of "from" is the same, the function modified a local copy
alert( from ); // Ann
Default values
If a parameter is not provided, then its value becomes undefined.
For instance, the aforementioned function showMessage(from, text) can be called with a
single argument:
showMessage("Ann");
That’s not an error. Such a call would output "Ann: undefined". There’s no text, so it’s
assumed that text === undefined.
If we want to use a “default” text in this case, then we can specify it after =:
function showMessage(from,
text = "no text given") {
alert( from + ": " + text );
}
Here "no text given" is a string, but it can be a more complex expression, which is only
evaluated and assigned if the parameter is missing. So, this is also possible:
In the example above, anotherFunction() is called every time showMessage() is called without
the text parameter.
Alternative default parameters
Sometimes it makes sense to set default values for parameters not in the function declaration,
but at a later stage, during its execution.
function showMessage(text) {
if (text === undefined) {
text = 'empty message';
}
alert(text);
}
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
Returning a value
A function can return a value back into the calling code as the result.
The simplest example would be a function that sums two values:
function sum(a, b) {
return a + b;
}
function checkAge(age) {
if (age >= 18) {
return true;
} else {
return confirm('Do you have permission from your parents?');
}
}
if ( checkAge(age) ) {
alert( 'Access granted' );
} else {
alert( 'Access denied' );
}
It is possible to use return without a value. That causes the function to exit immediately.
For example:
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
function doNothing() {
return;
}
return
(some + long + expression + or + whatever * f(a) + f(b))
That doesn’t work, because JavaScript assumes a semicolon after return. That’ll work the same
as:
return;
(some + long + expression + or + whatever * f(a) + f(b))
So, it effectively becomes an empty return.
If we want the returned expression to wrap across multiple lines, we should start it at the same
line as return. Or at least put the opening parentheses there as follows:
return (
some + long + expression
+ or +
whatever * f(a) + f(b)
)
And it will work just as we expect it to.
Naming a function
Functions are actions. So their name is usually a verb. It should be brief, as accurate as possible
and describe what the function does, so that someone reading the code gets an indication of
what the function does.
It is a widespread practice to start a function with a verbal prefix which vaguely describes the
action. There must be an agreement within the team on the meaning of the prefixes.
For instance, functions that start with "show" usually show something.
Two independent actions usually deserve two functions, even if they are usually called together
(in that case we can make a 3rd function that calls those two).
getAge – would be bad if it shows an alert with the age (should only get).
createForm – would be bad if it modifies the document, adding a form to it (should only
create it and return).
checkPermission – would be bad if it displays the access granted/denied message
(should only perform the check and return the result).
These examples assume common meanings of prefixes. You and your team are free to agree on
other meanings, but usually they’re not much different. In any case, you should have a firm
understanding of what a prefix means, what a prefixed function can and cannot do. All same-
prefixed functions should obey the rules. And the team should share the knowledge.
Ultrashort function names
Functions that are used very often sometimes have ultrashort names.
For example, the jQuery framework defines a function with $. The Lodash library has its core
function named _.
These are exceptions. Generally functions names should be concise and descriptive.
Functions == Comments
Functions should be short and do exactly one thing. If that thing is big, maybe it’s worth it to
split the function into a few smaller functions. Sometimes following this rule may not be that
easy, but it’s definitely a good thing.
A separate function is not only easier to test and debug – its very existence is a great comment!
For instance, compare the two functions showPrimes(n) below. Each one outputs prime
numbers up to n.
function showPrimes(n) {
nextPrime: for (let i = 2; i < n; i++) {
alert( i ); // a prime
}
}
The second variant uses an additional function isPrime(n) to test for primality:
function showPrimes(n) {
function isPrime(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
The second variant is easier to understand, isn’t it? Instead of the code piece we see a name of
the action (isPrime). Sometimes people refer to such code as self-describing.
So, functions can be created even if we don’t intend to reuse them. They structure the code
and make it readable.
Summary
A function declaration looks like this:
To make the code clean and easy to understand, it’s recommended to use mainly local
variables and parameters in the function, not outer variables.
It is always easier to understand a function which gets parameters, works with them and returns
a result than a function which gets no parameters, but modifies outer variables as a side-effect.
Function naming:
A name should clearly describe what the function does. When we see a function call in the
code, a good name instantly gives us an understanding what it does and returns.
A function is an action, so function names are usually verbal.
There exist many well-known function prefixes like create…, show…, get…, check… and so on.
Use them to hint what a function does.
Functions are the main building blocks of scripts. Now we’ve covered the basics, so we actually
can start creating and using them. But that’s only the beginning of the path. We are going to
return to them many times, going more deeply into their advanced features.
Tasks
Is "else" required?
importance: 4
The following function returns true if the parameter age is greater than 18.
function checkAge(age) {
if (age > 18) {
return true;
} else {
// ...
return confirm('Did parents allow you?');
}
}
function checkAge(age) {
if (age > 18) {
return true;
}
// ...
return confirm('Did parents allow you?');
}
Solution
No difference.
Rewrite the function using '?' or '||'
importance: 4
The following function returns true if the parameter age is greater than 18.
function checkAge(age) {
if (age > 18) {
return true;
} else {
return confirm('Did parents allow you?');
}
}
Rewrite it, to perform the same, but without if, in a single line.
For instance:
min(2, 5) == 2
min(3, -1) == -1
min(1, 1) == 1
solution
Function pow(x,n)
importance: 4
Write a function pow(x,n) that returns x in power n. Or, in other words, multiplies x by
itself n times and returns the result.
pow(3, 2) = 3 * 3 = 9
pow(3, 3) = 3 * 3 * 3 = 27
pow(1, 100) = 1 * 1 * ...* 1 = 1
Create a web-page that prompts for x and n, and then shows the result of pow(x,n).
P.S. In this task the function should support only natural values of n: integers up from 1.
solution
function pow(x, n) {
let result = x;
for (let i = 1; i < n; i++) {
result *= x;
}
return result;
}
if (n < 1) {
alert(`Power ${n} is not supported, use a positive integer`);
} else {
alert( pow(x, n) );
}