Functions
Functions are one of the fundamental building blocks in JavaScript. A function in JavaScript is similar to a procedure—a set of statements that performs a task or calculates a value, but for a procedure to qualify as a function, it should take some input and return an output where there is some obvious relationship between the input and the output. To use a function, you must define it somewhere in the scope from which you wish to call it.
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.
Defining functions
Function declarations
A function definition (also called a function declaration, or function statement) consists of the function
keyword, followed by:
- The name of the function.
- A list of parameters to the function, enclosed in parentheses and separated by commas.
- The JavaScript statements that define the function, enclosed in curly brackets,
{...}
.
For example, the following code defines a simple function named findSquare
:
function findSquare(num) {
return num * num;
}
The function square
takes one parameter, called num
. The function consists of one statement that says to return the parameter of the function (that is, num
) multiplied by itself. The statement return
specifies the value returned by the function:
return num * num;
Primitive parameters (such as a number) are passed to functions by value; the value is passed to the function, but if the function changes the value of the parameter, this change is not reflected globally or in the calling function.
If you pass an object (i.e. a non-primitive value, such as Array
or a user-defined object) as a parameter and the function changes the object's properties, that change is visible outside the function, as shown in the following example:
function makeBrand(theObject) {
theObject.make = 'Toyota';
}
var mycar = {make: 'Honda', model: 'Accord', year: 1998};
var x, y;
x = mycar.make; // x gets the value "Honda"
makeBrand(mycar);
y = mycar.make; // y gets the value "Toyota"
// (the make property was changed by the function)
Function expressions
While the function declaration above is syntactically a statement, functions can also be created by a function expression.
Such a function can be anonymous; it does not have to have a name. For example, the function findSquare
could have been defined as:
However, a name can be provided with a function expression. Providing a name allows the function to refer to itself, and also makes it easier to identify the function in a debugger's stack traces:
const sum = function addOperation(a,b) { return a+b }
console.log(sum(3,4))
myFunc
only if num
equals 0
:Calling functions
Defining a function does not execute it. Defining it names the function and specifies what to do when the function is called.
Calling the function actually performs the specified actions with the indicated parameters. For example, if you define the function findSquare
, you could call it as follows:
findSquare(5);
The preceding statement calls the function with an argument of 5
. The function executes its statements and returns the value 25
.
Functions must be in scope when they are called, but the function declaration can be hoisted (appear below the call in the code), as in this example:
console.log(findSquare(5));
/* ... */
function findSquare(n) { return n * n }
The scope of a function is the function in which it is declared (or the entire program, if it is declared at the top level).
Parameters
We can pass arbitrary data to functions using parameters.
In the example below, the function has two parameters: from
and text
.
function showMessage(from, text) { // parameters: from, text
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
When the function is called in lines (*)
and (**)
, the given values are copied to local variables from
and text
. Then the function uses them.
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:
function showMessage(from, text) {
from = '*' + from + '*'; // make "from" look nicer
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// the value of "from" is the same, the function modified a local copy
alert( from ); // Ann
When a value is passed as a function parameter, it’s also called an argument.
In other words, to put these terms straight:
- A parameter is the variable listed inside the parentheses in the function declaration (it’s a declaration time term)
- An argument is the value that is passed to the function when it is called (it’s a call time term).
We declare functions listing their parameters, then call them passing arguments.
In the example above, one might say: "the function showMessage
is declared with two parameters, then called with two arguments: from
and "Hello"
".
Default values
If a function is called, but an argument is not provided, then the corresponding 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"
. As the value for text
isn’t passed, it becomes undefined
.
We can specify the so-called “default” (to use if omitted) value for a parameter in the function declaration, using =
:
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
Now if the text
parameter is not passed, it will get the value "no text given"
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:
function showMessage(from, text = anotherFunction()) {
// anotherFunction() only executed if no text given
// its result becomes the value of text
}
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter.
In the example above, anotherFunction()
isn’t called at all, if the text
parameter is provided.
On the other hand, it’s independently called every time when text
is missing.
Alternative default parameters
Sometimes it makes sense to assign default values for parameters not in the function declaration, but at a later stage.
We can check if the parameter is passed during the function execution, by comparing it with undefined
:
function showMessage(text) {
// ...
if (text === undefined) { // if the parameter is missing
text = 'empty message';
}
alert(text);
}
showMessage(); // empty message
…Or we could use the ||
operator:
function showMessage(text) {
// if text is undefined or otherwise falsy, set it to 'empty'
text = text || 'empty';
...
}
Modern JavaScript engines support the nullish coalescing operator ??
, it’s better when most falsy values, such as 0
, should be considered “normal”:
function showCount(count) {
// if count is undefined or null, show "unknown"
alert(count ?? "unknown");
}
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;
}
let result = sum(1, 2);
alert( result ); // 3
The directive return
can be in any place of the function. When the execution reaches it, the function stops, and the value is returned to the calling code (assigned to result
above).
There may be many occurrences of return
in a single function. For instance:
function checkAge(age) {
if (age >= 18) {
return true;
} else {
return confirm('Do you have permission from your parents?');
}
}
let age = prompt('How old are you?', 18);
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;
}
alert( "Showing you the movie" ); // (*)
// ...
}
In the code above, if checkAge(age)
returns false
, then showMovie
won’t proceed to the alert
.
return
or without it returns undefined
If a function does not return a value, it is the same as if it returns undefined
:
function doNothing() { /* empty */ }
alert( doNothing() === undefined ); // true
An empty return
is also the same as return undefined
:
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
return
and the valueFor a long expression in return
, it might be tempting to put it on a separate line, like this:
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.
Predefined functions
JavaScript has several top-level, built-in functions:
isNaN()
The isNaN()
function determines whether a value is NaN
or not.
parseFloat()
The parseFloat()
function parses a string argument and returns a floating point number.
parseInt()
The parseInt()
function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
Arrow functions
Arrow function is one of the features introduced in the ES6 version of JavaScript. It allows you to create functions in a cleaner way compared to regular functions. For example,
This function
// function expression
let x = function(x, y) {
return x * y;
}
can be written as
// using arrow functions
let x = (x, y) => x * y;
using an arrow function.
Arrow Function Syntax
The syntax of the arrow function is:
let myFunction = (arg1, arg2, ...argN) => {
statement(s)
}
Here,
myFunction
is the name of the functionarg1, arg2, ...argN
are the function argumentsstatement(s)
is the function body
If the body has single statement or expression, you can write arrow function as:
let myFunction = (arg1, arg2, ...argN) => expression
Example 1: Arrow Function with No Argument
If a function doesn't take any argument, then you should use empty parentheses. For example,
let greet = () => console.log('Hello');
greet(); // Hello
Example 2: Arrow Function with One Argument
If a function has only one argument, you can omit the parentheses. For example,
let greet = x => console.log(x);
greet('Hello'); // Hello
Example 3: Arrow Function as an Expression
You can also dynamically create a function and use it as an expression. For example,
let age = 5;
let welcome = (age < 18) ?
() => console.log('Baby') :
() => console.log('Adult');
welcome(); // Baby
Things You Should Avoid With Arrow Functions
1. You should not use arrow functions to create methods inside objects.
let person = {
name: 'Jack',
age: 25,
sayName: () => {
// this refers to the global .....
//
console.log(this.age);
}
}
person.sayName(); // undefined
2. You cannot use an arrow function as a constructor. For example,
let Foo = () => {};
let foo = new Foo(); // TypeError: Foo is not a constructor
Note: Arrow functions were introduced in ES6. Some browsers may not support the use of arrow functions.
JavaScript Recursion
function recurse() {
// function code
recurse();
// function code
}
recurse();
recurse()
function is a recursive function. It is calling itself inside the function.A simple example of a recursive function would be to count down the value to 1.
Example 1: Print Numbers
// program to count down numbers to 1
function countDown(number) {
// display the number
console.log(number);
// decrease the number value
const newNumber = number - 1;
// base case
if (newNumber > 0) {
countDown(newNumber);
}
}
countDown(4);
Output
4 3 2 1
In the above program, the user passes a number as an argument when calling a function.
In each iteration, the number value is decreased by 1 and function
countDown()
is called until the number is positive. Here,newNumber > 0
is the base condition.This recursive call can be explained in the following steps:
countDown(4) prints 4 and calls countDown(3) countDown(3) prints 3 and calls countDown(2) countDown(2) prints 2 and calls countDown(1) countDown(1) prints 1 and calls countDown(0)When the number reaches 0, the base condition is met, and the function is not called anymore.
Comments
Post a Comment