JavaScript Functions

In this section of the tutorial, we will discuss Functions in JavaScript and their uses and different properties that are used as a reusable code block that can be invoked anywhere in the program with some good examples for in-depth understanding.

Now let’s move on further and understand the definition and some keypoints of Functions in JavaScript.

What are Functions in JavaScript?

A Function can be understood as a block of code written by a user which is defined once in a program but can be executed or invoked any number of times anywhere in the program.

  • In JavaScript, Functions are the building block of a program and it’s a common feature that is most commonly present in almost all programming languages.
  • The concept of functions has another name which we are familiar with, i.e. subroutine and procedure.
  • In JavaScript, Functions are parameterized which means that a function may include an identifier list called parameters, that works as a local variable for the function body.
  • When functions are invoked, they are provided with values called arguments to the function’s parameters.
  • In JavaScript, Function computes a return value using their argument values.
  • In each function invocation, there is a distinct value called the invocation context which is the value of the this keyword.

How can we define Functions in JavaScript?

In JavaScript, there are many ways of defining a function. One of the simplest way to define a function is by using the function keyword.

  • The function keyword can be used as a declaration or as an expression.
  • ES6 introduces a new way to define functions without using the function keyword. Instead, the arrow functions are used.
  • The arrow functions have a compact syntax.
  • Arrow functions are useful in passing one function as an argument to another function.
  • Another way of defining Functions is by using Function() Constructor.

Declaring Functions

In JavaScript, when a user wants to declare a function, he must use the function keyword followed by the following elements in the syntax:

  • Identifier naming the function, as the name of the function should be there while declaring a function. It is used as the name of a variable, then the defined function object is assigned to the variable.
  • It must have a pair of parathesis closed around a list of zero or more identifiers separated by comma. Such identifiers are the parameter names of the function and behave like local variables inside the body of the function.
  • It must have a pair of curly braces containing zero or more code statements inside it. These statements are the body of the function and executed when the function is invoked.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function printprops(o){
    for (let p in o){
        console.log('${p}: ${o[p]}\n');
    }
}

</script>
</head>
<body>
</body>
</html>
  • Here, a function printprops(o) is declared with o as parameter.
  • The body of the function has a console.log() statement that prints the name and value of each property of o.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function distance(x1, y1, x2, y2){
    let dx = x2 - x1;
    let dy = y2 - y1;
    return Math.sqrt(dx*dx + dy*dy)
}

</script>
</head>
<body>
</body>
</html>
  • Here, a function distance(x1, x2, y1, y2) is declared with x1, x2, x3, and x4 as parameters.
  • The body of the function Math.sqrt() function that computes and returns the distance between Cartesian points (x1, y1) and (x2, y2).

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function factorial(x){
    if (x <= 1) return 1;
    return x * factorial(x-1);
}

</script>
</head>
<body>
</body>
</html>
  • Here, a recursive function factorial(x) is declared with x as parameter.
  • The body of the function has a recursive statement that computes the factorial of the value of x.

Function Expression

In JavaScript, function expressions appear within the context of a larger expression or statement, where the name is optional. Function expression looks like function declaration but they both are different.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

const square = function(x) { return x*x };

const f = function fact(x) { if(x <= 1) return 1; else return x*fact(x-1);};

[3,2,1].sort(function(a,b) {return a-b; });

let tensquared = (function(x) {return x*x;}(10));

</script>
</head>
<body>
</body>
</html>
  • Here, in line 6, the function expression defines a function that squares its argument. It is assigned to a variable square.
  • In line 8, the function expressions include names, which is useful for recursion.
  • In line 10, the function expressions are used as arguments to other functions.
  • In line 12, the function expressions are defined and immediately invoked.

We must keep in mind that there is an important difference between defining as function f() with a function declaration and assigning a variable with a function after creating the function as an expression.

What are Arrow Functions in JavaScript?

In JavaScript ES6, a user can define a function using a more compact syntax knows as “arrow functions”.

  • The syntax of the Arrow Function is written using mathematical notation => which also separates the function parameters from the function body.
  • The function keyword is not used for Arrow Functions, since they are expressions instead of statements.
  • The general form of an Arrow Function is a comma-separated parameter list in parentheses followed by => which is then followed by the function body in the curly braces.

Example:

Another syntax of Arrow Function that is used if the body of the function is a single return statement, we can omit the return keyword. The semicolon and the curly braces go with it. Only the body of the function is written as an expression whose value is to be returned.

Example:

Also, we can omit the parentheses around the parameter list when the arrow function has exactly one parameter.

Example:

We should keep it in our mind that an arrow function having no arguments must be written with empty parentheses.

Example:

In situations where the body of an arrow function is a single return statement but the expression that is to be returned is an object literal, then we must put that object inside parentheses to avoid any syntactic ambiguity between curly braces of a function body and the curly braces of an object literal.

Example:

  • Here, in line 6, f() returns an object.
  • In line 8, g() returns an object.
  • In line 10, h() returns nothing (ambiguous syntax).
  • In line 12, there is a syntax error due to ambiguity.

Nested Functions

In JavaScript, we may come across situations where we have to nest a function within other functions, which is called Nesting of Functions.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function hypotenuse(a, b) {
    function square(x) { return x*x; }
    return Math.sqrt(square(a) + square(b));
}

</script>
</head>
<body>
</body>
</html>

In the above example, we can clearly note that the function square() is nested within the function hypotenuse().

Nested Function obeys the variable scoping rule that the parameters and variables of the function can be accessed by the function nested within.

How can we invoke a Function in JavaScript?

In JavaScript, for a given body of a function to execute, we must have to first invoke that function in the program.

The functions can be invoked in different ways:

  • Invoking as Functions
  • Invoking as Methods
  • Invoking as Constructors
  • Invoking indirectly using call() and apply()
  • Invoking implicit Function

We will discuss each of these ways in detail with suitable examples.

Invoking as Functions

In JavaScript, functions can be invoked as functions with an invocation expression. It consists of a function expression that evaluates to a function object inside an open parenthesis, a comma-separated list of zero or more arguments, and a close parenthesis.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

printprops({x: 1})
let total = distance(0,0,2,1) + distance(2,1,3,5);
let probability = factorial(5)/factorial(13);

</script>
</head>
<body>
</body>
</html>
  • Here, in an invocation, each of the arguments is evaluated and the computed value then becomes the value of the invocation expression.
  • These values are assigned to the parameters in the function definition.
  • Inside the function body, a reference to a parameter evaluates to the corresponding argument value.

Invoking as Methods

In JavaScript, a Method is a function that is stored in a property of an object.

Example: 

If a function f and an object are in a program, then we can define a method m of o by:

o.m = f;

Then we can invoke the method m() of the object o by:

o.m();

If we have two arguments for m(), it can be invoked by:

o.m(x, y);

We will take another example to understand the method invocation of functions.

Example:

Invoking as Constructors

In JavaScript, if a function or method is preceded by the keyword new, then such invocation is a constructor invocation.

In a constructor invocation, expressions in the argument list in parenthesis are evaluated and passed to the function as passed in a function or method invocation.

Example:

o = new Object();

o = new Object;
  • In the constructor invocation of a function, a new empty object is created that inherits from the object specified by the prototype property of the constructor.
  • This newly created object can be used as the invocation context, so the constructor function can refer to it with the keyword this.

Invoking indirectly using call() and apply()

In JavaScript, functions can be treated as objects, and all objects have methods. The two methods that can be used to invoke the function indirectly are call() and apply().

  • The call() and apply() methods allow us to explicitly specify the this value for the invocation that means any function can be invoked as a method of any object, even if it’s not actually a method of that object.
  • The call() method has its own argument list as arguments to the function.
  • The apply() method expects an array of values that is to be used as arguments.

Invoking implicit Function

In JavaScript, we have many features that won’t look like function invocations but that can be used to invoke functions.

  • When using such features, we have to be very careful when writing functions that are to be implicitly invoked.
  • Any wrong use of such features can throw bugs, cause side effects, and performance issues in these functions that are harder to diagnose and fix than in any regular functions.

Arguments and Parameters of Functions in JavaScript

In JavaScript, function definitions do not specify any expected type for the function parameters, and similarly, function invocation does not have type checking on argument values that are passed in it.

Further, we will discuss the behavior of a function under certain conditions like when a function is invoked with fewer arguments than the number of declared parameters or with more arguments than the number of declared parameters.

Optional parameters and Defaults

In situations when a function is invoked with fewer arguments than declared parameters, the additional parameters are set to their default value, which is generally undefined.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

let o = {x: 1}, p = {y: 2, z: 3};
let a = getPropertyNames(o);

getPropertyNames(p, a);

</script>
</head>
<body>
</body>
</html>
  • Here, we can see that the function getPropertyName() can be invoked with one or two arguments.
  • In line 6, two objects are created for testing.
  • In line 7, a == [“x”] will get o’s properties in a new array.
  • In line 9, a == [“x”, “y”, “z”] will add p’s properties to it.

Rest Parameters and Variable-Length Argument Lists

In a situation when we have to write functions that can be invoked with fewer arguments than the parameter, then we can use parameter defaults.

Rest parameters do the just opposite, they enable us to write functions that can be invoked with arbitrarily more arguments than parameters.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function max(first = -Infinity, ...rest) {
            let maxValue = first;
            
            for (let n of rest) {
                if(n > maxValue) {
                    maxValue = n;
                }
            }
            return maxValue;
}

max(1, 10, 100, 2, 3, 1000, 4, 5, 6)

</script>
</head>
<body>
</body>
</html>
  • Here, the first argument is assumed as the biggest.
  • Then the rest of the arguments are looped for finding the bigger argument.
  • Then the biggest argument value is returned.

Arguments Object

The identifier arguments refer to the Argument object for the invocation of varargs functions.

The Arguments object is an array-like object that retrieves the argument values passed to the function by a number rather than by name.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

function max(x) {
            let maxValue = -Infinity;
            
            for (let i = 0; i < arguments.length; i++) {
                if(arguments[i] > maxValue) maxValue = arguments[i];
            }
            return maxValue;
}

max(1, 10, 100, 2, 3, 1000, 4, 5, 6)

</script>
</head>
<body>
</body>
</html>

However, we should avoid using Argument Object as it is inefficient and hard to optimize.

Spread Operator for Functions

We use the spread operator to unpack or spread out the elements of an array or strings in a context where individual values are expected. It is used in the same way it was used in Array Literals in that we have learned in JavaScript Array tutorials.

Example:

<html>
<head>
<title>Arrays in JavaScript</title>
<script type="text/javascript">

let numbers = [5, 2, 10, -1, 9, 100, 1];
Math.min(...numbers)

</script>
</head>
<body>
</body>
</html>

In the next section of the tutorial, we will discuss Advanced Concepts of Functions in JavaScript such as Function as values, Function as namespaces, Functional Programming, and much more that are extensively used in the JavaScript program with some good examples for in-depth understanding.