JavaScript - tutorial - 05 - functions

revision:


Content

What is a JavaScript function? Specificities of functions Function parameters and arguments Function declaration Function expression Function() constructor Arrow functions A self-invoking function (IIFE) is invoked automatically, without being called. Closures Global functions - global methods and properties Functional programming: pure and impure functions Factory function Currying Functions examples


What is a JavaScript function?

top

A JavaScript function is a block of code designed to perform a particular task. The function is executed when "something" invokes it (calls it).

JavaScript functions are full fledged objects -- often called "first-class objects" -- having properties and methods, mutable values, and dynamic memory. Functions have the same capabilities as other objects; so they can be passed as arguments, returned from functions, assigned as data values, have properties and methods, and defined anywhere as an expression, allowing them to be nested.

Syntax: a JavaScript function is defined with the "function" keyword, followed by a name, followed by parentheses ()

function name(parameter1, parameter2, parameter3) { 
what the function does
}

Example: calculate area size

code:
                    <p class="spec" id="func1"></p>        
                    <script>
                    function calcRectArea(width, height) {
                        return width * height;
                    }
                    console.log(calcRectArea(5, 6));
                    document.getElementById("func1").innerHTML = "area size is " + calcRectArea(5,6);
                    // expected output: 30    
                    </script>
                

Outputting data

alert(): output data in an alert box in the browser window;

confirm(): opens up a yes/no dialog and returns true/false depending on user click;

console.log(): writes information to the browser console, good for debugging purposes;

document.write(): writes directly to the HTML document;

prompt(): creates an dialogue for user input;

Default values of functions

In JavaScript, you can have a function with a default argument value. This way you can call the function both with and without providing a value for the argument.

longhand

                    function pick(fruit) {
                        if(fruit === undefined){
                        console.log("I just picked up a Mango");
                        } else {
                        console.log(`I just picked up a ${fruit}`);
                        }
                    }
                

shorthand

                    function pick(fruit="Mango") {
                        console.log(`I just picked up a ${fruit}`)
                    }
                    pick("Pineapple");  // -> I picked up a Pineapple
                    pick();             // -> I picked up a Mango
                

Default parameter values

Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed. ES6 makes it possible to assign default to variables in the function declaration.

longhand

                        function volume(l, w, h) {
                            if (w === undefined)
                            w = 3;
                            if (h === undefined)
                            h = 4;
                            return l * w * h;
                        }
    
                        const add = (x, y) => {
                            if (x === undefined) {
                               x = 1;
                            }
                            if (y === undefined) {
                               y = 2;
                            }
                            return x + y;
                        }
    
                        function checkOut(quantity, price, discount){
                            if(discount === undefined){
                              discount = 0
                            }
                            return quantity * price + discount
                        }
    
                    

shorthand

                        volume = (l, w = 3, h = 4 ) => (l * w * h);
    
                        const add = (x = 1, y = 2) => x + y;
    
                        checkOut = (quantity, price, discount) => (quantity * price + discount)
                    

Mandatory parameter

By default, JavaScript will set function parameters to "undefined" if they are not passed a value. To enforce parameter assignment, you can use an "if statement" to throw an error if undefined, or you can take advantage of the "mandatory parameter shorthand". The mandatory argument indicates that the parameter is required. If this argument isn't specified, the parameter is optional.


longhand

                    function foo(bar) {
                        if(bar === undefined) {
                        throw new Error('Missing parameter!');
                        }
                        return bar;
                    }
            

shorthand

                    mandatory = () => {
                        throw new Error('Missing parameter!');
                    }
                
                    foo = (bar = mandatory()) => {
                        return bar;
                    }
            

Specificities of functions

top

"Function invocation" or "Function call": the code inside the function will execute when "something" invokes (calls) the function.

The code inside a function is executed when the function is invoked or called: e.g. when an event occurs (e.g. when a user clicks a button), when it is invoked (called) from JavaScript code, or automatically (self invoked).

It is common to use the term "call a function" instead of "invoke a function". It is also common to say "call upon a function", "start a function", or "execute a function".

With the "call() method", a method can be written that can be used on different objects. In JavaScript all functions are object methods. If a function is not a method of a JavaScript object, it is a function of the global object.

The example here below creates an object with 3 properties (firstName, lastName, fullName). The fullName property is a method.

Example

code:
                    <div class="spec">
                        <a id="func2"></a>  
                    </div>
                    <script>
                        var myObject = {
                            firstName:"John",
                            lastName: "Doe",
                            fullName: function() {
                                return this.firstName + " " + this.lastName;
                            }
                        }
                        x = myObject.fullName();
                        document.getElementById("func2").innerHTML = x; 
                    </script>
                

The JavaScript call() method - a predefined JavaScript method - can be used to invoke (call) a method with an owner object as an argument (parameter). With call(), an object can use a method belonging to another object.The call() method can accept arguments.

The example here below calls the fullName method of person, using it on person1 and person2.


code:
                    <div class=spec>
                        <a id="func3"></a><br>
                        <a id="func3A"></a>
                    </div>
                    <script>
                        var person = {
                            fullName: function(city, country) {
                                return this.firstName + " " + this.lastName + "," + city + "," + country;
                            }
                        }
                        var person1 = {
                            firstName:"John",
                            lastName: "Doe"
                        }
                        var person2 = {
                            firstName:"Mary",
                            lastName: "Doe"
                        }
                        var Y = person.fullName.call(person1, "Oslo", "Norway"); 
                        document.getElementById("idea2").innerHTML = Y; 
                        var Z = person.fullName.call(person2, "Oslo", "Norway"); 
                        document.getElementById("idea2A").innerHTML = Z; 
                    </script>
                

The apply() method is similar to the call() method, and can be used on different objects. The difference between call() and apply() : the call() method takes arguments separately; the apply() method takes arguments as an array.

In the example here below the fulllName method of person is applied on person1 and person2


code:
                    <div class="spec">
                        <a id="func4"></a><br>
                        <a id="func4A"></a>    
                    </div>
                    <script>
                            var person = {
                                fullName: function(city, country) {
                                    return this.firstName + " " + this.lastName + "," + city + "," + country;
                                }
                            }
                            var person1 = {
                                firstName:"John",
                                lastName: "Doe"
                            }
                            var person2 = {
                                firstName:"Mary",
                                lastName: "Doe"
                            }
                            var z = person.fullName.apply(person1, ["Oslo", "Norway"]); 
                            document.getElementById("func4").innerHTML = z; 
                            var zy = person.fullName.apply(person2, ["Oslo", "Norway"]); 
                            document.getElementById("func4A").innerHTML = zy; 
                    </script>
                

Function return: when JavaScript reaches a return statement, the function will stop executing.

If the function was invoked from a statement, JavaScript will "return" to execute the code after the invoking statement. Functions often compute a return value. The return value is "returned" back to the "caller".

Example: function "return"


code:
                    <div class="spec">
                        <a id="func5"></a><br>
                        <a id="func5A"></a>    
                    </div>
                    <script>
                        var x = mathFunction(4, 3);
                        var y = math2Function(4, 3);
                        document.getElementById("func5").innerHTML = x;
                        function mathFunction(a, b) {
                            return a * b;
                        }
                        document.getElementById("func5A").innerHTML = y;
                        function math2Function(a, b) {
                            return a / b;
                        }   
                    </script>
                
                

Functions can be used the same way as variables.

In all types of formulas, assignments, and calculations.

Examples: used as variable


code:
                    <div class="spec">
                        <a id="func6"></a><br>
                        <a id="func6A"></a>    
                    </div>
                    <script>
                    document.getElementById("func6").innerHTML = "The temperature is " + toCelsius(77) + " Celsius";
                    document.getElementById("func6A").innerHTML = "night temperature expected to be around" + toCelsius(63) + " Celsius";
                        function toCelsius(fahrenheit) {
                        return (5/9) * (fahrenheit-32);
                        } 
                    </script>
                

Local variables: variables declared within a function become LOCAL to the function.

Local variables can only be accessed from within the function. Since local variables are only recognized inside their functions, variables with the same name can be used in different functions. Local variables are created when a function starts, and deleted when the function is completed.

Examples: local variables


code:
                    <div class="spec">
                        <a id="func7"></a><br>
                        <a id="func7A"></a>    
                    </div>
                    <script>
                        carFunction();
                        function carFunction() {
                            let carName = "Volvo";
                            document.getElementById("func7").innerHTML =  typeof carName + " " + carName;
                        }
                        document.getElementById("func7A").innerHTML = typeof carName;
                    </script>
                

Function hoisting: JavaScript functions can be called before they are declared.

Hoisting is JavaScript's default behavior of moving declarations to the top of the current scope. Hoisting applies to variable declarations and to function declarations.

Examples: hoisting of functions


code:
                    <div class="spec">
                        <a id="func8"></a><br>
                        <a id="func8A"></a>    
                    </div>
                    <script>
                        x = 5; // Assign 5 to x
                        elem = document.getElementById("func8"); // Find an element 
                        elem.innerHTML = x;           // Display x in the element
                        var x; // Declare x
            
                        var xx; // Declare x
                        xx = 7; // Assign 5 to x
            
                        elem = document.getElementById("func8A"); // Find an element 
                        elem.innerHTML = xx;           // Display x in the element
            
                    </script>
                

Self-invoking functions : invoked (started) automatically, without being called.

Function expressions will execute automatically if the expression is followed by (). You cannot self-invoke a function declaration. You have to add parentheses around the function to indicate that it is a function expression.

Examples: self-invoking



code:
                    <div class="spec">
                        <a id="func9"></a><br><br> 
                        <a id="func9A"></a> 
                    </div>
                    <script>
                        (function () {
                            document.getElementById("func9").innerHTML = "Hello! I called myself!!";
                        })();
        
                        let sampleEle = document.querySelector("#func9A");
                        (function () {
                            sampleEle.innerHTML = "This code is invoked immediately as soon as it is defined";
                        })();
                    </script>
                

pipe (function composition)

We often need to “pipe” the output of one function as an input to another function.

Example - code

            const pipe = (...fns) => arg => 
            fns.reduce((v, fn) => fn(v), arg);   
        
            const pipe = (funA, funB, funC, ... , funN) =>
                (arg) => {funN( ... funC(funB(funA(arg)))); }
        
            const validationPipe = (...fns) => (...args) =>
                fns.reduce((res, func) => func(...args), ...args);
        

Function parameters and arguments

top

Function parameters are the names listed in the function definition. Function arguments are the real values passed to (and received by) the function.

Parameter rules: JavaScript function definitions do not specify data types for parameters and functions do not check the type of passed arguments and the number of arguments received.

Default parameters: if a function is called with missing arguments (less than declared), the missing values are set to undefined. Sometimes this is acceptable, but sometimes it is better to assign a default value to the parameter.

ES6 allows function parameters to have default values.
The rest parameter (...) allows a function to treat an indefinite number of arguments as an array.

Examples: parameters and arguments

code:
                    <div>
                        <p id="func10"></p>
                        <p id="func10A"></p>
                        <p id="func10B"></p>
                        <p id="func10C"></p>
                        
                    </div>
                    <script>
                        function firstFunction(x, y) {
                            if (y === undefined) {
                                y = 2;
                            }  
                            return x * y;
                        }
                        document.getElementById("func10").innerHTML = "result of function 1: " + firstFunction(4);
                        document.getElementById("func10A").innerHTML = "result of function 1: " + firstFunction(4,3);
                        
                        function secondFunction(x, y = 10) {
                            return x + y;
                        }
                        document.getElementById("func10B").innerHTML = "result of function 2: " + secondFunction(5);
        
                        function sum(...args) {
                            let sum = 0;
                            for (let arg of args) sum += arg;
                            return sum;
                        }
                        let x = sum(4, 9, 16, 25, 29, 100, 66, 77);
                        document.getElementById("func10C").innerHTML = "result of function sum: " + x;
                    </script>
                

The Arguments object : JavaScript functions have a built-in object, called the arguments object, which contains an array of the arguments used when the function was called (invoked). This way you can simply use a function to find (for instance) the highest value in a list of numbers or create a function to sum all input values.

Note: if a function is called with too many arguments (more than declared), these arguments can be reached using the arguments object.

Examples: arguments object

code:
                    <div>
                        <p id="func11"></p>
                        <p id="func11A"></p>
                        <p id="func11B"></p>
                    </div>
                    <script>
                        b = findMax(1, 123, 500, 115, 44, 88);
                        function findMax() {
                            let max = -Infinity;
                            for (let i = 0; i < arguments.length; i++) {
                                if (arguments[i] > max) {
                                    max = arguments[i];
                                }
                            }
                            return max;
                        }
                        document.getElementById("func11").innerHTML = "find maximum: " + b;
                        document.getElementById("func11A").innerHTML = "find maximum: " + findMax(4,5,7);
        
                        function sumAll() {
                            let sum = 0;
                            for(let i = 0; i < arguments.length; i++) {
                                sum += arguments[i];
                            }
                            return sum;
                        }
                        document.getElementById("func11B").innerHTML = "sum of numbers: " + sumAll(1, 123, 500, 115, 44, 88);            
                    </script>
                    
                

Arguments are passed by value: the parameters in a function call are the function's arguments. The function only gets to know the values, not the argument's locations. If a function changes an argument's value, it does not change the parameter's original value. Changes to arguments are not visible (reflected) outside the function.

Objects are passed by reference. In JavaScript, object references are values. Because of this, objects will behave like they are passed by reference: if a function changes an object property, it changes the original value. Changes to object properties are visible (reflected) outside the function.


Function declaration

top

Functions are "declared" with the following syntax:

 
        function functionName (parameters){ 
body/code to be executed
}

A function declaration is a statement that describes what the code does. Declarations are hoisted, which means they are loaded at the top of the scope before any other code runs.

Declared functions are not executed immediately. They are "saved for later use", and will be executed when they are invoked (called upon).

A function declaration can be broken down into the following pieces:

1/ name;
2/ parameters : a list of inputs that can be passed into a function;
3/ body : the logic or statements that perform the computation.

A function declaration on its own does not do anything. You make use of functions by calling them. The return value of the function can be assigned to a variable.

Function call: executes the code inside the function body.

Arguments: the values to be used as parameters in the function.

Return value: by default functions will return "undefined", but can return the result of a computation when the body contains a "return statement".

Parameters are the variables you use as inputs to your functions, while arguments are the actual values you pass to the functions when you call it.

Local variables: a variable declared inside a function is only visible inside that function.

Examples: local variables



code:
                    <div class="spec">
                        <a id="func13"></a><br><br>
                        <a id="func13A"></a>         
                    </div>
                    <script>
                        function showMessage(){
                            let message = "Hello, I'm JavaScript.";
                            document.getElementById('func13').innerHTML = "local variable: " + message;
                        }
                        showMessage();
                        document.getElementById('func13A').innerHTML = "error: " + message;// error: message is not defined
                    </script>
                

outer variables/global variables: global variables are visible from any function (unless shadowed by locals).

Examples: global variables











code:
                    <div class="spec">
                        <a id="func14"></a><br><br>
                        <a id="func14A"></a><br><br>
                        <a id="func14B"></a><br><br>
                        <a id="func14C"></a><br><br>
                        <a id="func14D"></a><br><br>
                        <a id="func14E"></a>         
                    </div>
                    <script>
                        let userName = "John";
                        function showMessage(){
                            let message = "message: " + ('Hello, ' + userName);
                            document.getElementById('func14').innerHTML = message;
                        }
                        showMessage();
        
                        let userName1 = "John";
                        function showMessage1(){
                            userName1 = "Bob"
                            let message = 'Hello, ' + userName1;
                            document.getElementById('func14A').innerHTML = "message: " +  message;
                        }
                        document.getElementById('func14B').innerHTML = "username: " + userName1;
                        showMessage1();
                        document.getElementById('func14C').innerHTML =  "username: " + userName1;
        
                        let userName2 = "John";
                        function showMessage2(){
                            let userName2 = "Bob"
                            let message = 'Hello, ' + userName2;
                            document.getElementById('func14D').innerHTML = "message: " + message;
                        }
                        showMessage2();
                        document.getElementById('func14E').innerHTML = "username: " + userName2;
                    </script>    
                

Examples: function declaration

code:
                    <p class="spec" id="func15"></p>
                    <script>
                    function calc_sales(units_a, units_b, units_c) {
                        return units_a * 79 + units_b * 129 + units_c * 699;
                    }
                    result = calc_sales(5, 6, 7);
                    document.getElementById("func15").innerHTML = "total of  units: " + result;    
                    </script>
                

code:
                    <p style="margin-left:5vw;" id="func16"></p>
                    <script>
                        function show() {  
                        document.getElementById("func16").innerHTML = "this is a function declaration.";     
                        }  
                        show(); 
                    </script>
                

code:
                    <p class="spec" id="func17"></p>
                    <script>
                        let alpha = calcFunction(4, 3);
                        document.getElementById("func17").innerHTML = "the result is: " + alpha;
                        function calcFunction(a, b) {
                            return a * b;
                        }
                    </script>  
                

code:
                    <p style="margin-left:5vw;"><span id="func18"></span></p>
                    <script>
                        var My_function = new Function("a","b","return a+b")
                        var beta = My_function(2,3)
                        document.getElementById("func18").innerHTML = "The sum is " + beta
                    </script>
                

code:
                    <p><span id="func19"></span></p>
                    <p><span id="func19A"></span></p>
                    <p><span id="func19B"></span></p>
                    <script>
                        let gamma = sum(1,2)
                        function sum(a, b){
                            return a + b
                        }
                        console.log(gamma);
                        console.log(sum(1, 2));
                        document.getElementById("func19").innerHTML = "the sum is " + gamma;
                        document.getElementById("func19A").innerHTML ="1 + 2 =" + sum(1,2);

                        function sayHiStranger(){
                            return 'Hi, Stranger!'
                        }
                        sayHiStranger();
                        document.getElementById("func19B").innerHTML = sayHiStranger();
                    </script>
                

Function expression

top

A JavaScript function can also be defined using an expression. A function expression can be stored in a variable. Function expressions are assigned to a variable as an expression.

Syntax:

 
            var x = function (parameters){ 
body/code to be executed
}

            function [name]([param1[, param2[, ..., paramN]]]) {
                statements
            }
        
            (function() {
                console.log('Code runs!')
            })();
        

Functions can be anonymous functions (functions without a name) or named functions. Functions stored in variables do not need function names. They are always invoked (called) using the variable name.

Unlike regular functions, function expressions are treated as expressions.

The function is a variable and is not hoisted on top of the scope. Hence, they can only be used once they are declared.

The main difference between a "function expression" and a "function declaration" is the function name, which can be omitted in function expressions to create anonymous functions.

A function expression can be used as an IIFE (Immediately Invoked Function Expression), which runs as soon as it is defined.

Examples: function expression















code:
 
                    <div class="spec">
                        <a id="func20"></a><br><br>
                        <a id="func20A"></a><br><br>
                        <a id="func20B"></a><br><br>
                        <a id="func20C"></a><br><br>
                        <a id="func20D"></a><br><br>
                        <a id="func20E"></a><br><br>
                        <a id="func20F"></a><br><br>
                    </div>
                    <script>
                        const speak = function(){
                            document.getElementById('func20').innerHTML = "speak = function(): " + 'good day!';
                            document.getElementById('func20A').innerHTML = "speak = function(): " + 'good day!';
                        };
                        speak();
                        
                        const square = function(x) {
                            return x * x;
                        };
                        document.getElementById('func20B').innerHTML = "square = function(): " +  (square(12));
                        
                        const makeNoise = function() {
                            document.getElementById('func20C').innerHTML = "makeNoise = function(): " + ("Pling!");
                        };
                        makeNoise();
                    
                        const power = function(base, exponent) {
                            let result = 1;
                            for (let count = 0; count < exponent; count++) {
                            result *= base;
                            }
                            return result;
                        };
                        document.getElementById('func20D').innerHTML = "power = function(): " + (power(2, 10));
                        
                        const halve = function(n) {
                            return n / 2;
                        };
                        let nn = 10;
                        document.getElementById('func20E').innerHTML = "halve = function(): " + (halve(100));
                        document.getElementById('func20F').innerHTML = "no function(): " + nn;
                    </script>
                

After a function expression has been stored in a variable, the variable can be used as a function.

Examples: function expression

code:
                    < id="func21"></p>
                    <script>
                        var myfun1 = function show() {  
                            document.getElementById("func21").innerHTML = "This is a function expression.";     
                            }  
                        myfun1();  
                    </script>
                



code:
                    <div>
                        <p><span id="func22"></span></p><br>
                        <p><span id="func22A"></span></p><br>
                        <p><span id="func22B"></span></p>
                    </div>
                    <script>
                        const total = function(a, b){
                            return a + b
                        }
                        total(2, 3);
                        console.log(total);
                        console.log(total(2, 3));
                        document.getElementById("func22").innerHTML = total; 
                        document.getElementById("func22A").innerHTML = "2 + 3 = " + total(2, 3);
        
                        const sayHiStranger1 = function(){
                            return 'Hi, Stranger!'
                        }
                        console.log(sayHiStranger1);
                        document.getElementById("func22B").innerHTML = sayHiStranger1();
        
                    </script>
                

Function() constructor

top

Functions can also be defined with a built-in JavaScript function constructor called "Function()".

Examples: function() constructor

code:
 
                    <div class="spec">
                        <a id="func23"></a> 
                    </div>
                    <script>
                        var myFunction = new Function("a", "b", "return a * b");
                        document.getElementById("func23").innerHTML = "new function(): " + myFunction(4, 3);
                    </script>
                

Arrow functions

top

Arrow functions allows a short syntax for writing function expressions. The "function" keyword, the "return" keyword, and the curly brackets are not needed. This is a concise syntax for creating functions, that's often better than Function Expressions.

syntax: let func = (arg 1, arg 2, arg 3, . . . argN) => expression

Arrow functions come in two flavors:

1/ without curly braces: (...args) => expression : the right side is an expression: the function evaluates it and returns the result.

2/ with curly braces: (...args) => { body } : brackets allow us to write multiple statements inside the function, but we need an "explicit return" to return something.

Arrow functions provide syntactic sugar for writing compact code, while also having some different features than functions declared with the "function" keyword.

An arrow function:

doesn't have its own "this" object; it is not well suited for defining object methods

has an implicit "return value" when brackets are omitted. i.e. () => true returns true.

is always an expression, never a statement; this means it is not hoisted and must be defined before it is used.

Using "const" in a arrow function is safer than using "var", because a function expression is always a constant value.

The "return" keyword and the curly brackets can only be omitted if the function is a single statement. Because of this, it might be a good habit to always keep them.

Examples: arrow functions















code:
                    <div class="spec">
                        <a id="func24"></a><br><br>
                        <a id="func24A"></a><br><br>
                        <a id="func24B"></a><br><br>
                        <a id="func24C"></a><br><br>
                        <a id="func24D"></a><br><br>
                        <a id="func24E"></a><br><br>
                        <a id="func24F"></a><br><br>
                        <a id="func24G"></a>     
                    </div>
                    <script>
                        let sum_1 = (a,b) => a + b;
                        document.getElementById('func24').innerHTML = "arrow function - sum: " + sum_1(1,2);
                            
                        let double = n => n * 2;
                        document.getElementById('func24A').innerHTML = "arrow function - multiplication: " + double(3);
                            
                        let sum_2 = (a, b) => { 
                            let result = a + b;
                                return result; 
                        };
                            
                        document.getElementById('func24B').innerHTML = "arrow function multiline - sum: " + sum_2(2, 3); 
        
                        const power_1 = (base, exponent) => {
                            let result = 1;
                            for (let count = 0; count < exponent; count++) {
                            result *= base;
                            }
                            return result;
                        };
                        document.getElementById('func24C').innerHTML = "arrow function loop - power: " + (power_1(2, 10));
        
                        const square_1 = (x) => { return x * x; };
                        document.getElementById('func24D').innerHTML = "arrow function - square: " + (square_1(5));
                        
                        const square_2 = x => x * x;
                        document.getElementById('func24E').innerHTML = "arrow function - square: " + (square_2(7));
        
                        const horn = () => {
                            document.getElementById('func24F').innerText = "arrow function - string: " + "Toot";
                        };  
                        horn(); 
                    </script>
                

An arrow function expression is a compact alternative to a traditional function expression

Arrow functions come in two flavors:

1/ without curly braces: (...args) => expression - the right side is an expression: the function evaluates it and returns the result;
2/ with curly braces: (...args) => { body } - brackets allow us to write multiple statements inside the function, but we need an explicit return to return something.

longhand

                    function sayHello(name) {
                    console.log('Hello', name);
                    }
                    
                    setTimeout(function() {
                        console.log('Loaded')
                    }, 2000);
                    
                    list.forEach(function(item) {
                        console.log(item);
                    });
                

shorthand

                    sayHello = name => console.log('Hello', name);

                    setTimeout(() => console.log('Loaded'), 2000);
                    
                    list.forEach(item => console.log(item));
                

With an arrow function, you can return an implicit result in a line of code.

longhand

                    function calcCircumference(diameter) {
                        return Math.PI * diameter
                    }
                

shorthand

                    calcCircumference = diameter => (
                        Math.PI * diameter;
                    )
                

A self-invoking function (IIFE) is invoked automatically, without being called.

top

Function expressions will execute automatically if the expression is followed by "()". It is crucial to add the parentheses around the function to indicate that it is a function expression.

Examples

code:
                    <p style="margin-left:5vw;" id="func25"></p>
                    <script>
                    (function (){
                        document.getElementById("func25").innerHTML = "This is a self-invoking function";
                    })();
                    </script>
                

An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined. It is a design pattern, which is also known as a "self-executing anonymous function" and contains two major parts:

The first is the anonymous function with lexical scope enclosed within the "Grouping Operator ()". This prevents accessing variables within the IIFE idiom as well as polluting the global scope.

The second part creates the immediately invoked function expression () through which the JavaScript engine will directly interpret the function.

IIFEs are very useful because they don't pollute the global object, and they are a simple way to isolate variables declarations.

If you declare a variable outside of a function, the JavaScript engine adds the variable to the global object.
If you have many global variables and functions, the JavaScript engine will only release the memory allocated for them until when the global object loses the scope. As a result, the script may use the memory inefficiently. On top of that, having global variables and functions will likely cause name collisions. One way to prevent the functions and variables from polluting the global object is to use immediately invoked function expressions.

Syntax: basic syntax

first version, ending with set of parenthesis.

                (function() {
                    // body of the function
                    })();
            

second version, ending with one parenthesis.

                    (function() {
                        // body of the function
                        }());
            

third version, starting with semicolon

                ;(function() {
                    // body of the function
                    }());
            

Syntax: IIFEs can be defined with arrow functions as well:

(() => {
                /* */
            })()
            

Syntax: an IIFE can also be named regular functions.

This does not change the fact that the function does not "leak" to the global scope, and it cannot be invoked again after its execution:

(function doSomething() {
            /* */
        })()
        

Syntax: IIFEs starting with a semicolon prevents issues when blindly concatenating two JavaScript files.

;(function() {
            /* */
        })()
        

Self-invoking functions - features and properties

Self-invoking functions are useful for initialization tasks and for one-time code executions, without the need of creating global variables.

Examples: self-invoking function

code:
                    <p style="margin-left:5vw;"><span id="func26"></span></p>
                    <script>
                        let sampleEle1 = document.querySelector("#func26");
                        (function () {
                            sampleEle1.innerHTML = "This code is invoked immediately as soon as it is defined";
                        })();
                    </script>
                

code:
                    <p style="margin-left:5vw;"><span id="func27"></span></p>
                    <script>
                        (function(){
                            document.getElementById("func27").innerText = Math.PI;
                        })();
                    </script>
                

Parameters can also be passed to self-invoking functions.

Examples: self-invoking function

code:
                    <div>
                        <p class="spec-2"><span id="func28"></span></p>
                        <p class="spec-2"><span id="func28A"></span></p>
                    </div>
                    <script>
                        (function(x){
                            document.getElementById("func28").innerHTML = x ;
                        })("Hello, world!");
        
                        (function(x){
                            document.getElementById("func28A").innerHTML = x ;
                        })(Math.PI);
                    </script>
                

A self-invoking function can have variables and methods but they cannot be accessed from outside of it. To access them, the global window object has to be passed as a parameter.

Examples: self-invoking function

;

code:
                    <p class="spec-2"><span id="func29"></span> ; <span id="func29A"></span></p>
                    <script>
                        (function(){
                            var pi = 3.141;
                            function e() {
                                return Math.E;
                            }
                            window.pi = pi;
                            window.e = e;
                            document.getElementById("func29").innerText = window.pi;
                            document.getElementById("func29A").innerText = window.e();
                        })(window);
                    </script>
                

This page was generated on:

code:
                    <p class="spec-2">This page was generated on: <span id="func30"></span></p>   
                    <script>
                        (function () {
                            date = new Date().toString();
                            document.querySelector('#func30').textContent = date;
                        })();
                    </script>
                

This page was generated on:

code:
                    <div>
                        <p class="spec-2">This page was generated on: <span id="func31"></span></p> 
                        <p class="spec-2"><span id="func31A"></span></p> 
                    </div>
                    <script>
                        (function () {
                            let date = new Date().toString();
                                document.querySelector('#func31').textContent = date;
                                // Assign to global window making it accessible to outside
                                window.date = date;
                            })();
                            document.querySelector('#func31A').textContent = 'The date accessed is: ' + date;

                    </script>
                

You can also use arrow functions with the IIFE pattern.

Examples: self-invoking function

code:
                    <p style="margin-left:5vw;"><span id="func32"></span></p> 
                    <script>
                        (() => {
                            console.log('Hello, World!');
                            result = ("Hello, world!");
                            document.getElementById("func32").innerText = result
                            })();
                    </script>
                

How to create an immediately invoked function expressions (IIFE)?

step 1: create an anonymous function that includes the "function" keyword, the parenthesis, the curly braces and the "console.log" statement.

This is a function declaration

example:

            function() {
                console.log('Say Hello');
            }
        

step 2: add a set of parenthesis to make it a self-invoking function.

Adding the parentheses turns a function declaration into a function expression.

example:

            function() {
                console.log('Say Hello');
            }();
        

step 3: wrap the function with another set of parenthesis to make it a fully functional IIFE.

The final parenthesis are calling that function expression, running the body of that function.

example:

           (function() {
                console.log('Say Hello');
            }());
        

Benefits of using IIFE

1/ while using IIFE, all variables and functions declared within the IIFE are local to the block.It is not possible for any code outside the block to access them. In other words, we can say IIFE provides complete encapsulation of variables and functions.

Examples: self-invoking function

code:
                    <p style="margin-left:5vw;"><span id="func33"></span></p>    
                    <script>
                    (function(name1, name2) {
                            console.log(name1 + ' & ' + name2);
                            result = (name1 + ' & ' + name2);
                            document.querySelector("#func33").textContent = result;
                        }("Romeo", "Juliet"));
                    </script>
                

2/ IIFE does not create unnecessary global variables and functions. You may also see IIFEs for cases where you want some temporary variables for one calculation that you don't want to expose to other calculations.

Examples: self-invoking function

code:
                    <div>
                        <p style="margin-left:5vw;"><span id="func34"></span></p>    
                        <p style="margin-left:5vw;"><span id="func34A"></span></p>
                    </div>
                    <script>   
                        (function () {
                            var x = 15;
                            document.getElementById("func34").innerText = "IIFE x : "+ x;
                        })();
                        document.getElementById("func34A").innerText = "Global x : "+ x; //Error
                    </script>
                

3/ Functions and variables defined in IIFE do not conflict with other functions and variables even if they have the same name. IIFEs are useful because they can define local variables that aren't accessible outside the IIFE. For example, IIFEs are often used to execute JavaScript in the browser without polluting global scope. It organizes JavaScript code and makes JavaScript code maintainable.

Examples: self-invoking function

code:
                    <div>
                        <p style="margin-left:5vw;"><span id="func35"></span></p>    
                        <p style="margin-left:5vw;"><span id="func35A"></span></p> 
                    </div>
                    <script>   
                        var x = 5;
                        (function () {
                            var x = 15;
                            document.getElementById("func35").innerHTML = "IIFE x : "+ x;
                        })();
                        document.getElementById("func35A").innerHTML = "Global x : "+ x;
                    </script>
                

4/ The benefit of using self-executing anonymous functions is that the variables we create inside of them are destroyed when the function exits. In this way, we can avoid conflicts between variable names, and we avoid holding variables in memory after they're no longer needed.

some more examples

Examples: self-invoking function

code:
                    <p style="margin-left:5vw;"><span id="func36"></span></p>
                    <script>
                        (function () {
                            var aName = "Alexander";
                            document.getElementById("func36").innerText = aName;    
                        })();
                    </script>
                

code:
                    <p style="margin-left:2vw;"><span id="func37"></span></p>
                    <script>
                        var result = (function () {
                            var name = "Alexander";
                            return name;
                        })();
                        document.getElementById("func37").innerText = result;
                    </script>
                

code:
                    <div>
                        <p style="margin-left:2vw;"><span id="func38"></span></p>
                        <p style="margin-left:2vw;"><span id="func38A"></span></p>
                        <p style="margin-left:2vw;"><span id="func38B"></span></p>
                    </div>
                    <script>
                        (function (x, y, z) {  
                            document.getElementById("func38").innerText = x;  
                            document.getElementById("func38A").innerText = y;  
                            document.getElementById("func38B").innerText = z;  
                        })(100, 200, "Alexander");  
                    </script> 
                

code:
                    <p style="margin-left:2vw;"><span id="func39"></span></p>
                    <script>
                        (function() { document.getElementById("func39").innerText = "Welcome to my website!"; })();
                    </script>;
                

code:
:
                    <p style="margin-left:2vw;"><span id="func40"></span> <span id="func40A"></span> <span id="func40B"></span></p>
                    <script>
                        function myFunc(){
                            document.getElementById("func40").innerText = "Welcome to ";
                            (function() { document.getElementById("func40A").innerText = " my updated coding page!"; })();
                            document.getElementById("func40B").innerText = "Hi There!";
                        }
                        // Calling the Function.
                        myFunc();
                    </script>
                

code:
                    <div>
                        <p style="margin-left:2vw;"><span id="func41"></span></p>
                        <p style="margin-left:2vw;"><span id="func41A"></span></p>
                    </div>
                    <script>
                        function msg() { 
                            document.querySelector("#func41").textContent = "This is the result of a regular functions!"; 
                        }; 
                        msg(); 
                        (function() { document.getElementById("func41A").innerHTML = "This is the result of an IIFE!"; })(); 
                    </script> 
                

code:
:
                    <div>
                        <p style="margin-left:2vw;"><span id="func42"></span></p>
                        <p style="margin-left:2vw;"><span id="func42A"></span></p>
                        <p style="margin-left:2vw;"><span id="func42B"></span></p>
                    </div>
                    <script>
                        function normal(what, is, normal){
                            return "This is normal."
                        }
                        result = normal();
                        document.querySelector("#func42").textContent = result;
                        let anonymous = function(what, is, anonymous){
                            return "This is anonymous."
                        }
                        document.querySelector("#func42A").textContent = anonymous();
                        (function (what, is, IIFE){
                            var a = "This is an IIFE.";
                            document.getElementById("func42B").innerHTML = a;
                        })("no");
                    </script>
                

code:
                    <p style="margin-left:2vw;"><span id="func43"></span></p>
                    <script>
                        var n = (function () {
                            var result = [],
                            len = 20,
                            i = 0;
                            while (i < len) {
                                result.push(Math.pow(2, i));
                                i += 1;
                            }
                            return result;
                        } ());
                        document.getElementById("func43").innerHTML = ( n.join(' , ') );            
                    </script>
                

code:
                    <div>
                        <p style="margin-left:2vw;"><span id="func44"></span></p>
                        <canvas style="margin-left: 2vw;" id="the-canvas" width="320" height="240"></canvas>
                    </div>
                    <script>
                        // make everything private with a js iife
                        (function () {
                            var canvas = document.getElementById('the-canvas'),
                            ctx = canvas.getContext('2d');
                            var cir = {
                                x: 32,
                                y: 16,
                                r: 10,
                                color: 'red'
                            };
                            var draw = function () {
                                ctx.fillStyle = 'black';
                                ctx.fillRect(0, 0, canvas.width, canvas.height);
                                ctx.fillStyle = cir.color;
                                ctx.beginPath();
                                ctx.arc(cir.x, cir.y, cir.r, 0, Math.PI * 2);
                                ctx.fill();
                            };
                            draw();
                        }());
                    </script>
                

Closures

top

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

A closure is a function having access to the parent scope, even after the parent function has closed. The closure has three scope chains listed as follows: access to its own scope, access to the variables of the outer function, and access to the global variables.

Examples

counting with a local variable.

0

0

code:
                    <div>
                        <p class="spec" style="margin-left: 5vw;">counting with a local variable.</p>
                        <button  style="margin-left: 5vw;" type="button" onclick="myCount()">Count!</button>
                        <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="func45">0</p>
                        <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="func45A">0</p>
                    </div>
                    <script>
                        const adding = (function () {
                            let counter = 0;
                            return function () {counter += 1; return counter;}
                        })();
        
                        function myCount(){
                        document.getElementById("func45").innerHTML = adding();
                        }
        
                        function niceFunction() {
                            let count = 0
                            function counter() {
                                count++
                                document.getElementById("func45A").innerHTML =  count;
                            }
                            setInterval(counter, 2000)
                        }
                        niceFunction()
                    </script>
                

Global variables can be made local (private) with closures.

Global variables: a function can access all variables defined inside the function. But a function can also access variables defined outside the function.

In a web page, global variables belong to the window object and can be used (and changed) by all scripts in the page (and in the window).

A local variable can only be used inside the function where it is defined. It is hidden from other functions and other scripting code. Global and local variables with the same name are different variables. Modifying one, does not modify the other.

NOTE: Variables created without a declaration keyword (var, let, or const) are always global, even if they are created inside a function.

Variable lifetime: Global variables live until the page is discarded, like when you navigate to another page or close the window. Local variables have short lives. They are created when the function is invoked, and deleted when the function is finished.

JavaScript nested functions: all functions have access to the global scope. In fact, in JavaScript, all functions have access to the scope "above" them. JavaScript supports nested functions. Nested functions have access to the scope "above" them.

A JavaScript closure makes it possible for a function to have "private" variables. A closure is a function having access to the parent scope, even after the parent function has closed.


Global functions - global methods and properties

top

decodeURI() — decodes a Uniform Resource Identifier (URI) created by encodeURI or similar

Syntax: decodeURI(uri)

parameters:

uri : Required. The URI to decode.

Examples

code:
                    <div>
                        <p id="func46"></p>
                    </div>
                    <script>
                        let uri = "my test.asp?name=ståle&car=saab";
                        let encoded = encodeURI(uri);
                        let decoded = decodeURI(encoded);
                        document.getElementById("func46").innerHTML = "Encoded URI:<br>" + encoded + "<br><br>" + "Decoded URI:<br>" 
                        + decoded;
                    </script>
                

decodeURIComponent() — decodes a URI component

Syntax: decodeURIComponent(uri)

parameters:

uri : required. The URI to be decoded.

Examples

code:
                    <div>
                        <p id="func47"></p>
                    </div>
                    <script>
                        let uri_a = "https://w3schools.com/my test.asp?name=ståle&car=saab";
                        let encoded_a = encodeURIComponent(uri);
                        let decoded_a = decodeURIComponent(encoded);
            
                        document.getElementById("func47").innerHTML = "Encoded URI:<br>" + encoded_a + "<br><br>" + "Decoded URI:<br>" + decoded_a;
                    
                

encodeURI() — encodes a URI into UTF-8

Syntax:encodeURI(uri)

parameters:

uri : Required. The URI to encode.

Examples

code:
                    <div>
                        <p id="func48"></p>
                    </div>
                    <script>
                        let uri_b = "my test.asp?name=ståle&car=saab";
                        let encoded_b = encodeURI(uri);
                        document.getElementById("func48").innerHTML = encoded_b;
            
                    </script>
                

encodeURIComponent() — same but for URI components

Syntax:encodeURIComponent(uri)

parameters:

uri : Required. The URI to be encoded.

Examples

code:
                    <div>
                        <p id="func49"></p>
                    </div>
                    <script>
                        let uri_c = "https://w3schools.com/my test.asp?name=ståle&car=saab";
                        let encoded_c = encodeURIComponent(uri_c);
                        document.getElementById("func49").innerHTML = encoded_c;
                    </script>
                

eval() — evaluates JavaScript code represented as a string;

Syntax:eval(string)

parameters:

string : A JavaScript expression, variable, statement, or sequence of statements

Executing JavaScript from a string is an BIG security risk. With eval(), malicious code can run inside your application without permission. With eval(), third-party code can see the scope of your application, which can lead to possible attacks.

Examples

code:
                    <div>
                        <p id="func50"></p>
                    </div>
                    <script>
                        let x = 10;
                        let y = 20;
                        let text_1 = "x * y";
                        let result_1 = eval(text_1);
                        document.getElementById("func50").innerHTML = result_1;
                    </script>        
                

Infinity — number that represents positive infinity; -Infinity - represents negative infinity

Syntax: Infinity

parameters: none

A number reaches Infinity when it exceeds the upper limit for a number: 1.797693134862315E+308.
A number reaches -Infinity when it exceeds the lower limit for a number: -1.797693134862316E+308.

Examples

code:
                    <div>
                        <p id="func51"></p>
                        <p id="func52"></p>
                    </div>
                    <script>
                        let p = 1.797693134862315E+308;
                        let q = p * 1.001;
                        document.getElementById("func51").innerHTML = q;
            
                        let r = -1.797693134862316E+308;
                        let s = r * 1.001;
                        document.getElementById("func52").innerHTML = s;
            
                    </script>
                    
                

isFinite() — determines whether a passed value is a finite number

Syntax: isFinite(value)

parameters:

value :Required. The value to be tested.

The isFinite() method returns true if a value is a finite number. Infinite (not finite) values are Infinity, -Infinity, or NaN

Examples

code:
                    <div>
                        <p id="func53"></p>
                        <p id="func53A"></p>
                        <p id="func53B"></p>
                        <p id="func53C"></p>
                    </div>
                    <script>
                        let result_22 = isFinite(123);
                        document.getElementById("func53").innerHTML = result_22;
                        let result_23 = isFinite("123");
                        document.getElementById("func53A").innerHTML = result_23;
                        document.getElementById("func53B").innerHTML = Number.isFinite("123");
                        document.getElementById("func53C").innerHTML = isFinite("123");
                    
                

isNaN() — determines whether a value is NaN or not

Syntax: isNaN(value)

parameters:

value : Required. The value to be tested.

isNaN() method returns true if a value is Not-a-Number. Number.isNaN() returns true if a number is Not-a-Number. In other words: isNaN() converts the value to a number before testing it.

Examples

code:
                    <div>
                        <p id="func54"></p>
                        <p id="func54A"></p>
                        <p id="func54B"></p>
                        <p id="func54C"></p>
            
                    </div>
                    <script>
                        let result_33 =
                        "Is 123 NaN? " + isNaN(123) + "
" + "Is -1.23 NaN? " + isNaN(-1.23) + "
" + "Is 5-2 NaN? " + isNaN(5-2) + "
" + "Is 0 NaN? " + isNaN(0); document.getElementById("func54").innerHTML = result_33; let result_34 = "Is '123' NaN? " + isNaN('123') + "
" + "Is 'Hello' NaN? " + isNaN('Hello') + "
" + "Is '2005/12/12' NaN? " + isNaN('2005/12/12'); document.getElementById("func54A").innerHTML = result_34; let text_33 = "Hello"; document.getElementById("func54B").innerHTML = isNaN(text_33); let text_34 = "Hello"; document.getElementById("func54C").innerHTML = Number.isNaN(text_34); </script>

Number() — returns a number converted from its argument

Syntax: Number(value)

parameters:

value : Optional. A JavaScript value (variable).

If the value cannot be converted, NaN is returned.

For booleans, Number() returns 0 or 1. For dates, Number() returns milliseconds since January 1, 1970 00:00:00. For strings, Number() returns a number or NaN.

Examples

code:
                    <div>
                        <p id="func55"></p>
                        <p id="func55B"></p>
                        <p id="func55C"></p>
                    </div>
                    <script>
                        document.getElementById("func55").innerHTML =
                            Number(true) + "<br>" + 
                            Number(false) + "<br>" + 
                            Number(new Date());
            
                        document.getElementById("func55A").innerHTML =
                            Number(999) + "<br>" + 
                            Number("999") + "<br>" + 
                            Number("999 888");
            
                        document.getElementById("func55B").innerHTML =
                            Number([9]) + "<br>" + 
                            Number([9.9]) + "<br>" + 
                            Number([9,9]);
                    </script>
                

parseFloat() — parses an argument and returns a floating point number

Syntax: parseFloat(value)

parameters:

value : Required. The value to parse.

If the first character cannot be converted, NaN is returned. Leading and trailing spaces are ignored. Only the first number found is returned.

Examples

code:
                    <div>
                        <p id="func56"></p>
                        <p id="func56A"></p>
                    
                    </div>
                    <script>
                        document.getElementById("func56").innerHTML =
                            parseFloat(10) + "<br>" +
                            parseFloat("10") + "<br>" +
                            parseFloat("10.33") + "<br>" +
                            parseFloat("34 45 66") + "<br>" +
                            parseFloat("He was 40");
                        
                        document.getElementById("func56A").innerHTML =
                            parseFloat("40.00") + "<br>" +
                            parseFloat("   40   ") + "<br>" +
                            parseFloat("40 years") + "<br>" +
                            parseFloat("40H") + "<br>" +
                            parseFloat("H40");
            
                    </script>
                

parseInt() — parses its argument and returns an integer;

Syntax: parseInt(string, radix)

parameters:

value : Required. The value to be parsed.radix : Optional. Default is 10. A number (2 to 36) specifying the number system.

The parseInt method parses a value as a string and returns the first integer. A radix parameter specifies the number system to use: 2 = binary, 8 = octal, 10 = decimal, 16 = hexadecimal. If radix is omitted, JavaScript assumes radix 10. If the value begins with "0x", JavaScript assumes radix 16.
If the first character cannot be converted, NaN is returned. Leading and trailing spaces are ignored. Only the first integer found is returned.
Older browsers will return 8 for parseInt("010"). Older versions of ECMAScript used octal (radix 8) for values beginning with "0". From ECMAScript 5 (2009) default is decimal (radix 10).

Examples

code:
                    <div>
                        <p id="func57"></p>
                        <p id="func57A"></p>
                    </div>
                    <script>
                        document.getElementById("func57").innerHTML =
                            parseInt("10") + "<br>" +
                            parseInt("10.00") + "<br>" +
                            parseInt("10.33") + "<br>" +
                            parseInt("34 45 66") + "<br>" +
                            parseInt("   60   ") + "<br>" +
                            parseInt("40 years") + "<br>" +
                            parseInt("He was 40");
                        document.getElementById("func57A").innerHTML =
                            parseInt("10", 10)+ "<br>" +
                            parseInt("010")+ "<br>" +
                            parseInt("10", 8)+ "<br>" +
                            parseInt("0x10")+ "<br>" +
                            parseInt("10", 16);
                    </script>
                

String() — converts a value to a string.

Syntax: String(value)

parameters:

value : Required. A JavaScript value.

The String() method returns the same as the toString() method for any value.

Examples

code:
                    <div>
                        <p id="func58"></p>
                        <p id="func58A"></p>
                    </div>
                    <script>
                        document.getElementById("func58").innerHTML =
                            String(new Date()) + "<br>" +
                            String("12345") + "<br>" +
                            String(12345);
                        document.getElementById("func58A").innerHTML =
                            String(Boolean(0)) + "<br>" +
                            String(Boolean(1)) + "<br>" +
                            String([1,2,3,4]);  
                    </script>
                

undefined — indicates that a variable has not been assigned a value, or not declared at all.

Examples

code:
                    <div>
                        <p id="func59"></p>
                        <p id="func59A"></p>
                        <p id="func59B"></p>
                    </div>
                    <script>
                        let xy;
                        if (xy === undefined) {
                        text_55 = "xy is undefined";
                        } else {
                        text_55 = "xY is defined";
                        }
                        document.getElementById("func59").innerHTML = text_55;
            
                        let xz;
                        if (typeof xz === "undefined") {
                        text_56 = "xz is undefined";
                        } else {
                        text_56 = "xz is defined";
                        }
                        document.getElementById("func59A").innerHTML = text_56;
            
                        if (typeof yz === "undefined") {
                            text_57 = "yz is undefined";
                        } else { 
                            text_57 = "yz is defined";
                        }
                        document.getElementById("func59B").innerHTML = text_57;
                    </script>
            
                

Functional programming: pure and impure functions

top

Functional programming distinguishes between "pure" and "impure" functions and encourages to write pure functions.

A pure function must satisfy both of the following properties:

a/ referential transparency : the function always gives the same return value for the same arguments; this means that the function cannot depend on any mutable state.
b/ side-effect free : the function cannot cause any side effects; side effects may include I/O (e.g., writing to the console or a log file), modifying a mutable object, reassigning a variable, etc.

A pure function only relies on its inputs, produces no side effects, and does not modify values outside its local scope.

A pure function is a deterministic function: when a same input is passed every time, the function will return the same output. In mathematical terms it is nothing but "a well defined" function.

A pure function will have the following properties:

it depends only on its own arguments;

it won't try to change variables out of its scope;

it doesn't produce any side effects.

examples

        function pure(arg) {
               return 4 * arg;
            }
        document.write(pure(2));
    
        function calculateGST( productPrice ) {
            return productPrice * 0.05;
        }
    

example: not pure function

        var tax = 20;
        function calculateGST( productPrice ) {
            return productPrice * (tax / 100) + productPrice;
        }
    

There are four main types of functions.

1/ First class functions are functions that can be assigned as values to variables, returned from other functions, and passed as arguments to other functions.

2/ Callback functions are functions that are passed into other functions as arguments and are called by the function in which they are passed.

3/ Higher order functions are functions that receive other functions as arguments or return a function.

A higher order function (HOF) is created by combining (or composing) multiple functions together by passing (1) functions as arguments or (2) returning functions. Higher-order functions are those functions that take other functions as arguments OR return other functions. The function passed as arguments in higher-order function is known as a callback.

There are many built-in JS functions that use HOF, for example setTimeout(), Array.map(), filter() and reduce().

example

        function calculate(numbers) {
            let sum = 0;
            for (const number of numbers) {
              sum = sum + number;
            }
            return sum;
        }
        calculate([1, 2, 4]); // => 7
    
        const numbers = [1, 2, 4];
        const doubled = numbers.map(function mapper(number) {
            return 2 * number;
        });
        doubles; // [2, 4, 8]
        

4/ Anonymous functions are functions that don't have a name and cannot be reused. These functions are normally written when we need to carry out something once and in only one place.

Some principles need to be understood in order to qualify for functional programming:

Avoid changing things. A function should not change anything, such as a global variable.

Function must be pure, meaning it has no side effects. In functional programming, changes that are made are called mutations, and the outcomes are called side effects.

Abstractions hide details and allow to talk about problems at a higher level without describing all the implementation details of the problem.

Filtering arrays: when working with data structures like arrays, we are most likely to find ourselves in a situation where we are only interested in certain items in the array. To obtain these items we can easily create a function to do the task.

Examples

example 1: imperative programming

array: [1, 2, 3, 4, 5, 6, 7, 8, 9]

code:
                <div>
                    <p class="ex">example 1: imperative programming</p>
                    <p style="margin-left: 5vw;">array: [1, 2, 3, 4, 5, 6, 7, 8, 9]</p>        
                    <p style="margin-left: 5vw;" id="func60"></p>     
                    <p style="margin-left: 5vw;" id="func60A"></p>   
                </div>
                <script>
                    const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                    function getOdds(arr) {
                        let odds = [];
                        for (let i = 0; i < arr.length + 1; i++) {
                            if (i % 2 !== 0) {
                                odds.push(i);
                            }
                        }
                        return odds;
                    }
                    function getEvens(arr) {
                        let evens = [];
                        for (let i = 0; i < arr.length + 1; i++) {
                            if (i % 2 === 0) {
                                evens.push(i);
                            }
                        }
                        return evens;
                    }
                    document.getElementById("func60").innerHTML =  "odd numbers: " + getOdds(arr);
                    document.getElementById("func60A").innerHTML =  "even  numbers: " + getEvens(arr); 
                </script>    
            

The imperative approach is to define a data structure, and then manipulate it in order to obtain the output we need.

Examples

example 2: imperative programming

array: [1, 2, "3", "4", 5, 6, "7", 8, "9"]

code:
                <div>
                    <p class="ex">example 2: imperative programming</p>
                    <p style="margin-left: 5vw;">array: [1, 2, "3", "4", 5, 6, "7", 8, "9"]</p>       
                    <p style="margin-left: 5vw;" id="func61"></p>     
                    <p style="margin-left: 5vw;" id="func61A"></p>     
                </div>
                <script>
                    const arr22 = [1, 2, "3", "4", 5, 6, "7", 8, "9"];
                    function even(el) {
                        return el % 2 === 0;
                    }
                    function odd(el) {
                        return el % 2 !== 0;
                    }
                    // Converting string to number in array
                    const arrAsNumbers = arr22.map(function (el) {
                        return Number(el);
                    });
                   // Filtering even numbers
                    const filteredArr = arrAsNumbers.filter(function (el) {
                        return even(el);
                    });
                    // Filtering odd numbers
                    const filteredOdd = arrAsNumbers.filter(function (el) {
                        return odd(el);
                    });
                                  
                    document.getElementById("func61").innerHTML = "even numbers: " + filteredArr;  
                    document.getElementById("func61A").innerHTML = "odd numbers: " + filteredOdd; 
                </script>
            

Examples

example 3: functional programming

array: [1, 2, 3, 4, 5, 6, 7, 8, 9]

code:
                <div>
                    <p style="margin-left: 5vw;">array: [1, 2, 3, 4, 5, 6, 7, 8, 9]</p>     
                    <p style="margin-left: 5vw;"id="func62"></p>
                    <p style="margin-left: 5vw;"id="func62A"></p>        
                </div>
                <script>
                    function getOdds2(arr){
                        return arr.filter(num => num % 2 !== 0)
                        }
                    document.getElementById("func62").innerHTML = "odd numbers: " + (getOdds2(arr));
                    const getEvens2 = arr => arr.filter(num => num % 2 === 0);
                    document.getElementById("func62A").innerHTML = "even numbers: " + (getEvens2(arr));
                </script>
            

In a functional approach, we use filter functions to define a programmed function, and then invoke this as needed.

why use functional programming?

Functional programming results in shorter code that is more easily read, understood, and audited.

Functional code is easier to read than imperatively defined code.

Functional programming ensures code integrity with penetration testing.

key tools for functional programming

1/ Pure and impure functions.

At the most basic level, a functional approach seeks to manipulate data without mutating them. A "functional function" will take data, perform some calculations, and return a result (and all without re-writing any part of the data structure itself). Functions that work in this way are called "pure" functions, and those that do not are called "impure".

2/ Anonymous functions.

Anonymous functions are also an important part of functional programming, and one that has its roots in Lambda Calculus. Anonymous functions do not have an explicitly defined name. Instead, they are functions that are assigned to variables, and invoked via them.

3/ Recursive functions. The use of recursive functions is another mark of functional programming.

A recursive function is one that calls itself from inside its own function body. If a terminating condition is not provided, it will create and "infinite loop". A recursive function always has a condition to stop calling itself. Otherwise, it will call itself indefinitely.

Recursive functions are commonly used in algorithm implementations to efficiently handle tasks like binary-tree traversal.

examples

        function recurse() {
            if(condition) {
                // stop calling itself
                //...
            } else {
                recurse();
            }
        }
    
        // program to find the factorial of a number
        function factorial(x) {
            // if number is 0
            if (x === 0) {
                return 1;
            }
            // if number is positive
            else {
                return x * factorial(x - 1);
            }
        }
        const num = 3;
       // calling factorial() if num is non-negative
        if (num > 0) {
            let result = factorial(num);
            console.log(`The factorial of ${num} is ${result}`);
        }
    

Factory function

top

A factory function is a function that returns a new object. Functions create functions or objects. For example, a function that allows to create user objects.

Factory functions in JavaScript are similar to constructor functions/class functions, but they do not require the use of the 'this' keyword for inner values or the use of the 'new' keyword when instantiating new objects.

Factory functions can contain inner values, methods, etc. just like normal regular functions. Factory Functions differ from regular functions as they always return an object, which will contain any value, method, etc.

Examples

code:
                <div>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="func63"></p>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="func63A"></p>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="func63B"></p>
                </div>
                <script>
                    function createRobot(name) {
                        return {
                            name: name,
                            talk: function () {
                                document.getElementById("func63").innerHTML += 'My name is ' 
                                + name + ', the robot.' + "<br>";
                                console.log('My name is ' + name + ', the robot.');
                            }
                        };
                    }
    
                    const robo1 = createRobot('Chitti');
                    robo1.talk();
                    const robo2 = createRobot('Chitti 2.O Upgraded');
                    robo2.talk();

                    var Person = function (name, age) {
                        var person = {};
                        person.name = name;
                        person.age = age;
                        person.greeting = function () {
                            return ( 'Hello I am ' + person.name + '. I am ' + person.age  + ' years old. ');
                        };
                        return person;
                    };

                    var person1 = Person('Arthur', 20);
                    console.log(person1.greeting());
                    document.getElementById("func63A").innerHTML = person1.greeting();

                    var person2 = Person('Rajeev', 35);
                    console.log(person2.greeting());
                    document.getElementById("func63B").innerHTML = person2.greeting();
            </script>
            

Currying

top

currying is a design pattern where a function is immediately evaluated and returns a second function. This pattern let execute specialization and composition.

Currying is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c). Currying doesn't call a function. It just transforms it.

Currying is defined as changing a function having multiple arguments into a sequence of functions with a single argument. It is a process of converting a function with more arity into a function having less arity. The term arity means the number of parameters in a function.

Examples

code:
                <div>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="fun64"></p>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="fun64A"></p>
                    <p class="spec" style="margin-left: 5vw;margin-top: 1vw;" id="fun64B"></p>
                </div>
                <script>
                    function curry(fn) {
                        return function (a) {
                            return function (b) {
                                return fn(a, b);
                            };
                        };
                    } 
                    function sum(a, b) {
                        return a + b;
                    }
                    let currySum = curry(sum);
                    document.getElementById("fun64").innerHTML = currySum(10)(20);
                    console.log(currySum(10)(20)); // 30

                    function mul(val1){  
                        return function(val2){  
                            document.getElementById("fun64A").innerText +=  (val1 * val2) + ", "; 
                            console.log(val1 * val2); 
                        }  
                    }  
                    
                    let a = mul(2); 
                    a(5); 
                    a(6);  
    
            </script>
            

Functions examples

top

Examples

code:
                    <script>
                        let add = (function(a,b){
                             return a + b;
                         })(10, 20);
                         document.getElementById("func65").innerHTML = "total: " + add;
                    </script>
                

code:
                    <script>
                        (function() {
                             var counter = 0;
                             function add(a, b) {
                                 return a + b;
                             }
                             console.log(add(20,40)); 
                             document.getElementById("func66").innerHTML = "total: " + add(20,40);
                         }());
                     </script>
                

code:
                    <script>
                        (function (message) {
                          console.log(message);
                          document.getElementById("func67").innerHTML = message;
                        })('Hello World');
                     </script>
                

code:
                    <script>
                        // All of these are equivalent, leading semicolon is optional
                         ;(() => console.log('Hello'))();
                         ;(function(){ console.log('Hello'); })();
                         ;(function(){ console.log('Hello'); })();
                         ;(function(){ console.log('Hello'); }());
         
                         ;(() => document.getElementById("func68").innerHTML = 'Hello')();
                         ;(function(){ document.getElementById("func68A").innerHTML = 'Hello'; })();
                         ;(function(){ document.getElementById("func68B").innerHTML = 'Hello'; })();
                         ;(function(){ document.getElementById("func68C").innerHTML = 'Hello'; }());
         
                    </script>
                

code:
                    <script>
                        var x = 5;
                        (function () {
                            var x = 15;
                            console.log("IIFE x : "+ x);
                            document.getElementById("func69").innerHTML = "IIFE x: " + x;
                        })();
                        console.log("Global x : "+ x)
                        document.getElementById("func69A").innerHTML = "Global x: " + x;
                   </script>
                    
                
Github - function examples
function-apply:
                const numbers = [5, 6, 2, 3, 7];
                const max = Math.max.apply(null, numbers);           
                console.log(max);
                // expected output: 7
                const min = Math.min.apply(null, numbers);
                console.log(min);
                // expected output: 2
            
function-bind:
                const module = {
                    x: 42,
                    getX: function() {
                    return this.x;
                    }
                };
                const unboundGetX = module.getX;
                console.log(unboundGetX()); // The function gets invoked at the global scope
                // expected output: undefined
                const boundGetX = unboundGetX.bind(module);
                console.log(boundGetX());
                // expected output: 42
            
function-call:
                function Product(name, price) {
                    this.name = name;
                    this.price = price;
                }
                function Food(name, price) {
                    Product.call(this, name, price);
                    this.category = 'food';
                }
                console.log(new Food('cheese', 5).name);
                // expected output: "cheese"
            
function-constructor:
                const sum = new Function('a', 'b', 'return a + b');
                console.log(sum(2, 6));
                // expected output: 8
            
function-length:
                function func1() {}
                function func2(a, b) {}
                console.log(func1.length);
                // expected output: 0
                console.log(func2.length);
                // expected output: 2
            
function-name:
                const func1 = function() {};
                const object = {
                    func2: function() {}
                };
            console.log(func1.name);
                // expected output: "func1"
                console.log(object.func2.name);
                // expected output: "func2"     
            
function-tostring:
                function sum(a, b) {
                    return a + b;
                }
                console.log(sum.toString());
                // expected output: "function sum(a, b) {
                //                     return a + b;
                //                   }"
                console.log(Math.abs.toString());
                // expected output: "function abs() { [native code] }"
            
functions-arguments:
                function func1(a, b, c) {
                    console.log(arguments[0]);
                    // expected output: 1
                    console.log(arguments[1]);
                    // expected output: 2
                    console.log(arguments[2]);
                    // expected output: 3
                }
                func1(1, 2, 3);
            
functions-arrows:
                const materials = [
                    'Hydrogen',
                    'Helium',
                    'Lithium',
                    'Beryllium'
                ];
                console.log(materials.map(material => material.length));
                // expected output: Array [8, 6, 7, 9]
            
functions-default:
                function multiply(a, b = 1) {
                    return a * b;
                }
                console.log(multiply(5, 2));
                // expected output: 10
                console.log(multiply(5));
                // expected output: 5
            
functions-definitions:
                const obj = {
                    foo() {
                    return 'bar';
                    }
                };
                console.log(obj.foo());
                // expected output: "bar"
            
functions-getter:
                const obj = {
                    log: ['a', 'b', 'c'],
                    get latest() {
                    if (this.log.length === 0) {
                        return undefined;
                        }
                        return this.log[this.log.length - 1];
                    }
                };
                console.log(obj.latest);
                // expected output: "c"
            
functions-restparameters:
                function sum(...theArgs) {
                    return theArgs.reduce((previous, current) => {
                    return previous + current;
                    });
                }
                console.log(sum(1, 2, 3));
                // expected output: 6
                console.log(sum(1, 2, 3, 4));
                // expected output: 10
            
functions-setter:
                const language = {
                    set current(name) {
                    this.log.push(name);
                    },
                    log: []
                };
                language.current = 'EN';
                language.current = 'FA';
                console.log(language.log);
                // expected output: Array ["EN", "FA"]
            

JavaScript.info - examples

function declaration:
                function showMessage() {
                    alert( 'Hello everyone!' );
                }
            
local variables:
                function showMessage() {
                    let message = "Hello, I'm JavaScript!"; // local variable
                    alert( message );
                }
                showMessage(); // Hello, I'm JavaScript!
                alert( message ); // <-- Error! The variable is local to the function
            
outer variables:
                let userName = 'John';
                function showMessage() {
                    let message = 'Hello, ' + userName;
                    alert(message);
                }
                showMessage(); // Hello, John

                let userName = 'John';
                function showMessage() {
                    userName = "Bob"; // (1) changed the outer variable
                    let message = 'Hello, ' + userName;
                    alert(message);
                }
                alert( userName ); // John before the function call
                showMessage();
                alert( userName ); // Bob, the value was modified by the function

                let userName = 'John';
                function showMessage() {
                let userName = "Bob"; // declare a local variable
                let message = 'Hello, ' + userName; // Bob
                alert(message);
                }
                // the function will create and use its own userName
                showMessage();
                alert( userName ); // John, unchanged, the function did not access the outer variable
            
parameters:
                function showMessage(from, text) { // parameters: from, text
                    alert(from + ': ' + text);
                }
                showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
                showMessage('Ann', "What's up?"); // Ann: What's up? (**)

                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
            
default values:
                function showMessage(from, text = "no text given") {
                    alert( from + ": " + text );
                }
                showMessage("Ann"); // Ann: no text given

                showMessage("Ann", undefined); // Ann: no text given

                function showMessage(from, text = anotherFunction()) {
                    // anotherFunction() only executed if no text given
                    // its result becomes the value of text
                }
            
returning a value:
                function sum(a, b) {
                    return a + b;
                }
                let result = sum(1, 2);
                alert( result ); // 3
                
                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' );
                }

                function showMovie(age) {
                    if ( !checkAge(age) ) {
                    return;
                    }
                    alert( "Showing you the movie" ); // (*)
                    // ...
                }
            
function expressions:
                let sayHi = function() {
                    alert( "Hello" );
                };
                
                function sayHi() {
                    alert( "Hello" );
                }
                alert( sayHi ); // shows the function code

                function sayHi() {   // (1) create
                    alert( "Hello" );
                }
                let func = sayHi;    // (2) copy
                func(); // Hello     // (3) run the copy (it works)!
                sayHi(); // Hello    //     this still works too (why wouldn't it)
            
callback functions:
                function ask(question, yes, no) {
                    if (confirm(question)) yes()
                    else no();
                }
                function showOk() {
                    alert( "You agreed." );
                }
                function showCancel() {
                    alert( "You canceled the execution." );
                }
                // usage: functions showOk, showCancel are passed as arguments to ask
                ask("Do you agree?", showOk, showCancel);

                function ask(question, yes, no) {
                    if (confirm(question)) yes()
                    else no();
                }
                ask(
                    "Do you agree?",
                    function() { alert("You agreed."); },
                    function() { alert("You canceled the execution."); }
                );
            
arrow functions:
                let sum = (a, b) => a + b;
                /* This arrow function is a shorter form of:
                let sum = function(a, b) {
                    return a + b;
                };
                */
                alert( sum(1, 2) ); // 3

                let double = n => n * 2;
                // roughly the same as: let double = function(n) { return n * 2 }
                alert( double(3) ); // 6

                let sayHi = () => alert("Hello!");
                sayHi();

                let age = prompt("What is your age?", 18);
                let welcome = (age < 18) ?
                    () => alert('Hello!') :
                    () => alert("Greetings!");
                welcome();
            
multiline arrow functions:
                let sum = (a, b) => {  // the curly brace opens a multiline function
                    let result = a + b;
                    return result; // if we use curly braces, then we need an explicit "return"
                };
                alert( sum(1, 2) ); // 3