
Writing and Invoking Functions
Functions are the basic building blocks when it comes to writing JavaScript programs. A function is one or more statements that can optionally receive data input and provide data output. The statements in a function are not used until the function is invoked. Invoking a function is also known as calling the function.
Defining Functions
JavaScript offers a few ways to define a function. We are going to look at function declarations, function expressions, and arrow function expressions as ways to define a function.
Function Declaration
You can define a function as a statement. This is called a function definition or declaration. The syntax is as follows:
function name(optional parameter list) {
//Statements
//Optional return statement
}
It starts a line of code with the function keyword. It is followed by a name. The name is how the function will appear in other code. The list of comma-separated parameters are names for the input values to a function. Parameters are essentially variables within the function. They are enclosed in parentheses. The block statement then contains the code. Once a function is declared, it can be invoked either on a line of code by itself or within an expression. In the case of its use in an expression, the function typically returns data.
When a JavaScript function is declared as a statement, it can be invoked by statements that appear before it. This is called hoisting.
Let's have a look at an example of defining and invoking a function declaration. This example has no parameters and returns the value of a single dice roll:
function getDiceRollValue(){
return Math.floor(Math.random() * 6) + 1;
}
Since it returns a value, we can use it as an expression. Here is an example where it is used in an addition expression to get the roll value of two dice:
var rollValue = getDiceRollValue() + getDiceRollValue();
We could improve the function so that it returns the value of a set number of dice by creating a parameter. Here, the parameter is the number of dice being rolled:
function getDiceRoll(numberOfDice){
var rollValue = 0;
for (let i = 1; i<= numberOfDice; i++){
rollValue += Math.floor(Math.random() * 6) + 1;
}
return rollValue;
}
The revised expression to invoke for simulating a two-dice roll just requires us to pass the parameter values. In this example, the parameter is expressed as a number literal:
var rollValue = getDiceRollValue(2);
In this example, the parameter is expressed as a variable:
var numberOfDice = 2;
var rollValue = getDiceRollValue(numberOfDice);
Parameters can be optional, otherwise the wrong data can be passed. So, functions often have code that validates the parameter or provides a default value. In this example, the argument of the JavaScript built-in function known as parseInt is used to convert the argument into an integer. Its results are tested using the isNaN built-in function, which returns true or false if the number is not a number or the number is less than 1. If any of that is true, the argument value is set to 1. If not, the supplied number is passed through:
function getDiceRoll(numberOfDice){
numberOfDice = (isNaN(parseInt(numberOfDice)) || numberOfDice< 1) ?1 :numberOfDice;
var rollValue = 0;
for (let i = 1; i<= numberOfDice; i++){
rollValue += Math.floor(Math.random() * 6) + 1;
}
return rollValue;
}
Now, the function always returns a roll of one dice, regardless of an incorrect parameter or no parameter. In both of these examples, the value of the roll of one dice is returned:
var rollValue = getDiceRoll();
var rollValue = getDiceRoll("BOGUS");
Exercise 3.14: Writing a Function as a Statement and Invoking It
This exercise will define a function as a statement and then use it. The function we will create will accept one parameter and return an array. If the parameter can be validated as a number, then each item in the array has one digit from the number starting with the 0 index item holding the digit for the ones place value, the 1 index item holding the digit for the tens place value, and so on.
We will use the log method of the console object in this exercise. Remember that a method is a function that belongs to an object, so it can have parameters. The log method takes an unlimited number of parameters. Let's get started:
- Open the function-declare.html document in your web browser.
- Open the web developer console window using your web browser.
- Open the function-declare.js document in your code editor, replace all of its content with the following code, and then save it.
This declares the function. Its name is getDigitsOfNumber. It has one parameter named num. It returns the digits array:
function getDigitsOfNumber(num){
var digits = [];
console.log("num:", num);
return digits;
}
- Reload the function-declare.html web page in your web browser with the console window open.
There is no output because the function was not invoked.
- Edit the function-declare.js document, add the following bolded text to the end of the file, and then save it.
In this example, the function is being expressed and is not being invoked. Invoking a function requires to append parentheses around the function's name:
return digits;
}
console.log("getDigitsOfNumber:", getDigitsOfNumber);
- Reload the function-declare.html web page in your web browser with the console window open.
The function is treated as data and is displayed:
getDigitsOfNumber: ƒ getDigitsOfNumber(num){
var digits = [];
console.log("num:", num);
return digits;
}
- Edit the function-declare.js document, update it using the following bolded text at the end of the file, and then save it.
This invokes the function in an assignment statement to create the test456 variable:
return digits;
}
var test456 = getDigitsOfNumber(456);
console.log("test456:", test456);
This will add the value of the property or method.
- Reload the function-declare.html web page in your web browser with the console window open. The first line of output shows the num parameter being displayed when the function was invoked. The second output line is the test456 variable being set to the empty array that was returned by the function:
num: 456
test456: =>[]
- Edit the function-declare.js document, add the following bolded text to the beginning of the file, and then save it. This shows invoking the function before it is declared. This demonstrates hoisting:
var test123 = getDigitsOfNumber(123);
console.log("test123:", test123);
function getDigitsOfNumber_1(num){
- Reload the function-declare.html web page in your web browser with the console window open. These are the results for the invocations of the function before and after it was declared:
num: 123
test123: =>[]
num: 456
test456: =>[]
- Edit the function-declare.js document, update it using the following bolded text, and then save it.
The second line in the function converts any negative numbers into positive numbers and truncates any decimals. The if statement tests to assure that the num parameter contains a number. The while loop repeats until the num parameter becomes zero. Inside the loop, the ones place value is added to the digits array by dividing by 10 and using the remainder. Then, the ones place value is stripped from the num parameter:
function getDigitsOfNumber(num){
var digits = [];
num = Math.floor(Math.abs(num));
if(!isNaN(num)){
while(num != 0) {
digits.push(num % 10);
num = Math.floor(num / 10);
}
}
return digits;
}
- Reload the function-declare.html web page in your web browser with the console window open.
Each array shows the test value digits split into arrays. The zero-array index has the ones place value, the one array index has the tens place value, and the two-index position has the hundreds place value:
test123: =>(3) [3, 2, 1]
test456: =>(3) [6, 5, 4]
- Edit the function-declare.js document, add the following bolded text to the end of the file, and then save it. You can run various tests on your functions based on the possible inputs and expected outputs. These are a few for you to try.
An intermediate variable is not used for these new lines. A function can be used wherever an expression can be used. In these additions, it is used as an expression for a log method parameter:
var test456 = getDigitsOfNumber(456);
console.log("test456:", test456);
console.log('5:', getDigitsOfNumber(5));
console.log('4563:', getDigitsOfNumber(4563));
console.log('123.654:', getDigitsOfNumber(123.654));
console.log('-123.654:', getDigitsOfNumber(-123.654));
console.log('"1000"', getDigitsOfNumber("1000"));
console.log('"1,000"', getDigitsOfNumber("1,000"));
console.log('"B37"', getDigitsOfNumber("B37"));
console.log('"37B"', getDigitsOfNumber("37B"));
- Reload the function-declare.html web page in your web browser with the console window open.
Here are the outputs. The expected results should be an array with all the digits or an empty array. Evaluate each output and verify that this was the result. If the output was an empty array, determine why:
test123: =>(3) [3, 2, 1]
test456: =>(3) [6, 5, 4]
5: =>[5]
4563: =>(4) [3, 6, 5, 4]
123.654: =>(3) [3, 2, 1]
-123.654: =>(3) [3, 2, 1]
"1000" =>(4) [0, 0, 0, 1]
"1,000" =>[]
"B37" =>[]
"37B" =>[]
In this exercise, we defined a function as a statement that accepts one parameter and return an array. We used the log method of the console object in this exercise.
Function Expression
In this variation, you can define a function as part of an expression. There is no name for the function. However, because a function is a data type, it can be assigned to a variable. The variable can then be used to invoke the function. The syntax is as follows:
function(optional parameter list) {
//Statements
//Optional return statement
}
The syntax is the same, except no function name is needed. A JavaScript function declared as an expression cannot be invoked by statements that appear before it.
Here is an example of defining and invoking a function expression.
This example shows the function as part of an assignment expression. The right-hand side of the assignment is the function without a name. The left-hand side is the variable:
var getDiceValue = function(){
return Math.floor(Math.random() * 6) + 1;
}
In this case, the variable can be used to invoke the function:
var rollValue = getDiceValue() + getDiceValue();
Exercise 3.15: Writing a Function as an Expression and Invoking It
This exercise defines a function as an expression and then uses it.
The function returns a single random character from a string. The string is the function's only parameter. If the parameter is not a string or is an empty string, then an empty string is returned. Let's get started:
- Open the function-expression.html document in your web browser.
- Open the web developer console window using your web browser.
- Open the function-expression.js document in your code editor, replace all of its contents with the following code, and then save it.
The function, as a literal value, is assigned to the getRandomStringCharacter variable.
Then, the variable is displayed in the console. Remember, a function is not invoked unless you include parentheses:
var getRandomStringCharacter = function(source){
var returnCharacter = '';
console.log("source:", source);
return returnCharacter;
}
console.log('getRandomStringCharacter', getRandomStringCharacter);
- Reload the function-expression.html web page in your web browser with the console window open. The actual function is displayed but not invoked, as expected:
getRandomStringCharacter ƒ (source){
var returnCharacter = '';
console.log("source:", source);
return returnCharacter;
}
- Edit the function-expression.js document, update the lines with the following bolded text, and then save it.
Now, we will invoke the function:
return returnCharacter;
}
getRandomStringCharacter();
getRandomStringCharacter("AEIOU");
- Reload the function-expression.html web page in your web browser with the console window open.
The console.log statement in the function displays the source parameter value for each invocation. No parameter was passed in the first invocation. The source parameter data type is undefined:
source: undefined
source: AEIOU
- Edit the function-expression.js document, add the following bolded text above the function, and then save it.
Now, we will invoke the function before it is defined:
getRandomStringCharacter();
var getRandomStringCharacter = function(source){
var returnCharacter = '';
- Reload the function-expression.html web page in your web browser with the console window open.
You should see an error in the console. Functions that are defined as expressions cannot be invoked before they are defined:
Uncaught TypeError: getRandomStringCharacter is not a function
at function-expression.js:1
- Edit the function-expression.js document, update the bolded text, and then save it.
We can remove the line that invokes the function before it is defined and finish coding the function. The if block tests whether the source parameter is not undefined and contains characters. In the if block, the Math.floor(Math.random() * source.length expression finds a random character position as a value from 0 to the length of the source parameter minus 1. The charAt string method extracts the character at that position it will be returned at:
var getRandomStringCharacter = function(source){
if (source !=undefined &&source.length> 0){
returnCharacter = source.charAt(Math.floor(Math.random() * source.length));
}
return returnCharacter;
}
These lines are a set of tests of various source values. The first passes no parameter. The second, third, and fourth pass a string. The fifth is passing a number and the last is passing a Boolean:
console.log('():', getRandomStringCharacter());
console.log('("AEIOU"):', getRandomStringCharacter('AEIOU'));
console.log('("JavaScript"):', getRandomStringCharacter('JavaScript'));
console.log('("124678"):', getRandomStringCharacter('124678'));
console.log('(124678):', getRandomStringCharacter(124678));
console.log('(true):', getRandomStringCharacter(true));
- Reload the function-expression.html web page in your web browser with the console window open.
The function's output expects a random character in the source parameter. If it is not empty, it will return a string and will return an empty string for all other values. Reload the web page a few times to get different test results:
():
("AEIOU"): U
("124678"): 6
("JavaScript"): a
(124678):
(true):
Arrow Function Expression
Arrow functions were introduced in ES6. They are defined similarly in an expression, such as when defining function expressions. They offer syntactically compact alternatives over defining a function expression. There is nothing different in how they are invoked. The => symbol is the telltale sign of an arrow function being defined. Also, the function keyword is not used. The concise variation, without a function body, can return an expression with or without a return statement. This differs from a function expression, which requires the return statement to return a value. The syntax is as follows:
(optional parameter list) => {
//Statements
//Optional return statement
}
(optional parameter list) => //Expression or return statement
Parameter parentheses are optional when a single parameter is named:
parameter => {
//Statements
//Optional return statement
}
parameter => //Expression or return statement
Parentheses are required if there is no parameter:
() => {
//Statements
//Optional return statement
}
() =>//Expression or return statement
JavaScript arrow functions cannot be invoked by statements that appear before it.
Defining and Invoking an Arrow Function Expression
This example shows a single statement arrow function with no parameters. The right-hand side of the assignment is the function without a name. The left-hand side is the variable:
var getDiceValue = ()=> Math.floor(Math.random() * 6) + 1;
In this case, the variable can be used to invoke the function:
var rollValue = getDiceValue() + getDiceValue();
This example shows a multiple statement arrow function with one parameter. The right-hand side of the assignment is the function without a name. The left-hand side is the variable:
var getDiceRoll = (numberOfDice) => {
numberOfDice = (isNaN(parseInt(numberOfDice)) || numberOfDice< 1) ?1 :numberOfDice;
var rollValue = 0;
for (let i = 1; i<= numberOfDice; i++){
rollValue += Math.floor(Math.random() * 6) + 1;
}
return rollValue;
}
The following is the output of invoking and passing a parameter:
var rollValue = getDiceRoll(2);
Exercise 3.16: Writing an Arrow Function and Invoking It
This exercise will show you how to convert a function expression into an arrow function. The JavaScript file we'll be using already contains the function. Let's get started:
- Open the function-arrow.html document in your web browser.
- Open the web developer console window using your web browser.
- Reload the function-arrow.html web page in your web browser with the console window open.
The first, second from last, and last results are an empty string. The second, third, and fourth results show a random character from the string:
():
("AEIOU"): U
("124678"): 6
("JavaScript"): a
(124678):
(true):
- Open the function-arrow.js document in your code editor, make changes to the bolded lines, and then save it:
var getRandomStringCharacter = (source) => {
var returnCharacter = '';
if (source !=undefined &&source.length> 0){
returnCharacter = source.charAt(Math.floor(Math.random() * source.length);
}
return returnCharacter;
}
- Reload the function-arrow.html web page in your web browser with the console window open.
The results are the same. The first, second from last, and last results are an empty string. The second, third, and fourth results show a random character from the string:
():
("AEIOU"): I
("124678"): 2
("JavaScript"): J
(124678):
(true):