Blog

  • Rest Parameter

    Rest Parameter

    The rest parameter in JavaScript allows a function to accept a variable number of arguments as an array. When the number of arguments that need to pass to the function is not fixed, you can use the rest parameters.

    The JavaScript rest parameters allow you to collect all the remaining arguments in a single array. The rest parameter is represented with three dots (…) followed by a parameter name. This parameter name is the array that contains all the remaining arguments.

    Rest Parameter Syntax

    The rest parameter in JavaScript involves using three dots (…) followed by a parameter name in the function declaration.

    functionfunctionName(para1, para2, ...theArgs){// function body;}

    Here para1, and para2 are ordinary parameters while theArgs is a rest parameter. The rest parameter collects the rest of arguments (here, arguments other than the corresponding to the parameters para1 and para1) and assigns to an array named theArgs.

    We can write the rest parameter in function expression also same as in the function declaration.

    The rest parameter should always be the last parameter in the function definition.

    functionfuncName(...para1, para2, para2){}// SyntaxError: Invalid or unexpected token

    The function definition can have only one rest parameter.

    functionfuncName(para1, ...para2, ...para3){}//SyntaxError: Rest parameter must be last formal parameter  

    Example: Variable Length Parameter List

    The rest parameters are very useful when you want to define a function that can handle a variable number of arguments. Lets take the following example −

    <html><body><div> Rest parameter allows function to accept nay number of arguments.</div><div id ="demo"></div><script>functionsum(...nums){let totalSum =0;for(let num of nums){
    
        totalSum += num;}return totalSum;}
    document.getElementById("demo").innerHTML =sum(10,20,30,40)+"&lt;br&gt;"+sum(10,20)+"&lt;br&gt;"+sum();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Rest parameter allows function to accept nay number of arguments.
    100
    30
    0
    

    Here, the rest parameter nums allows the function to accept any number of number arguments.

    Example: Finding the Maximum Number

    JavaScript rest parameter simplifies the process of finding the max number among a set of given numbers.

    In this example, we use rest parameter to numbers to collect all arguments passed to the function. The spread operator is used to pass the individual values to the Math.max() function.

    <html><body><div> Finding the maximum number</div><div id ="demo"></div><script>functiongetMax(...args){return Math.max(...args);} 
    
      document.getElementById("demo").innerHTML =getMax(10,20,30,40)+"&lt;br&gt;"+getMax(10,20,30);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Finding the maximum number
    40
    30
    

    Here the rest parameter args allows the function getMax to accept any number of arguments.

    Spread Operator and Rest Parameters

    The spread operator (...) is closely related to rest parameters and is often used in conjunction with them. While the rest parameter collects function arguments into an array, the spread operator performs the opposite operation, spreading the elements of an array into individual arguments.

    In the above example of finding the maximum number, we used both rest parameter and spread operator.

    functiongetMax(...args){// here ...args as rest parameterreturn Math.max(...args);// here ... works as spread operator}

    Example

    In this example, the spread operator ... is used to pass the elements of the numbers array as individual arguments to the multiply function.

    <html><body><div> Spread operator in JavaScript<div><div id="demo"></div><script>functionmultiply(a, b, c){return a * b * c;}const numbers =[2,3,4];
    
      document.getElementById("demo").innerHTML =multiply(...numbers);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Spread operator in JavaScript
    24
    

    Rest Parameter vs. Arguments Object

    The introduction of rest parameters has implications for how we handle variable-length parameter lists compared to using the arguments object. Let's compare the two approaches:

    Rest Parameters

    <html><body><div> Sum using rest parameter in JavaScript:</div><div id ="demo"></div><script>functionsum(...numbers){return numbers.reduce((total, num)=> total + num,0);}
    
    document.getElementById("demo").innerHTML =sum(1,2,3,4,5);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Sum using rest parameter in JavaScript:
    15
    

    Arguments Object

    <html><body><div> Sum using arguments object in JavaScript:</div><div id ="demo"></div><script>functionsum(){const argsArray = Array.from(arguments);return argsArray.reduce((total, num)=> total + num,0);}
    
    document.getElementById("demo").innerHTML =sum(1,2,3,4,5);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Sum using arguments object in JavaScript:
    15
    

    While both approaches achieve the same result, the rest parameter syntax is more concise and readable. It also behaves more consistently with other modern JavaScript features.

    Destructuring with Rest Parameter

    The destructuring assignment is introduced in ES6. It allows us to access the individual values of the array without using array indexing. We can use the destructuring assignment to extract the values from the array created by rest parameter.

    Example

    In the example below, the destructuring assignment extracts the first two elements from the numbers array.

    <html><body><div> Destructuring assignment with rest parameter</div><div id ="demo"></div><script>functiongetFirstTwo(...numbers){const[first, second]= numbers;returnFirst: ${first}, Second: ${second};} 
    
    document.getElementById("demo").innerHTML =getFirstTwo(1,2,3,4,5);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Destructuring assignment with rest parameter
    First: 1, Second: 2

  • Atomics Objects

    The Atomics object in JavaScript provides a set of static methods for performing atomic operations on SharedArrayBuffer objects. Atomic operations are operations that are guaranteed to be completed in a single step, without being interrupted by other threads. This makes them useful for implementing concurrent data structures and algorithms.

    The Atomics object in JavaScript, as part of the ECMAScript standard, serves as a crucial tool for managing shared memory in a multi-threaded environment. Let’s understand the basic concept of atomic operations in more detail:

    Atomics Object

    The Atomics object is a built-in JavaScript object that provides atomic operations on shared memory. It is designed to be used in a multi-threaded environment, where multiple threads or Web Workers may be concurrently accessing and modifying shared data.

    The Essence of “Atomic”

    In the context of the Atomics object, “atomic” signifies a crucial characteristic: it performs operations that are inherently indivisible. When we declare an operation as atomic; we imply its execution occurs continuously and uninterruptedly like a single unit. This quality is indispensable in preventing race conditions; these arise when concurrent operations’ outcomes depend on their timing and sequence of execution.

    Atomic Operations

    Atomic operations are low-level operations on shared memory that are guaranteed to be executed as a single, uninterruptible unit. These operations include additions, subtractions, bitwise operations, exchanges, and more.

    The Atomics object provides methods like add, sub, and, or, xor, load, store, exchange, and others, each corresponding to a specific atomic operation.

    Sr.No.Method & Description
    1Atomics.add()Adds a specified value to the element at the specified index in the typed array. Returns the original value atomically.
    2Atomics.sub()Subtracts a specified value from the element at the specified index in the typed array. Returns the original value atomically.
    3Atomics.and()Performs an atomic bitwise AND operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    4Atomics.or()Performs an atomic bitwise OR operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    5Atomics.xor()Performs an atomic bitwise XOR operation on the element at the specified index in the typed array with the given value. Returns the original value atomically.
    6Atomics.load()Retrieves the value at the specified index in the typed array atomically.
    7Atomics.store()Stores the given value at the specified index in the typed array atomically.
    8Atomics.exchange()Swaps the value at the specified index in the typed array with a specified value. Returns the original value atomically.
    9Atomics. compareExchange()Compares the value at the specified index in the typed array with a provided expected value, and if they match, updates the value with a new value. Returns the original value atomically.
    10Atomics.wait()Atomically waits for a value at the specified index in the typed array to be a specific value and then returns. Allows for efficient coordination between threads.
    11Atomics.notify()Atomically notifies the wait queue associated with the specified index in the typed array.

    Examples

    Example 1: Basic Usage of Atomics Operations

    In this example, the Atomics object is demonstrated for its fundamental atomic operations on shared memory. These operations include addition, subtraction, bitwise AND, OR, XOR, loading, storing, exchanging, and compare-exchanging values. Each operation ensures the indivisibility of the executed unit, crucial for preventing race conditions in a multi-threaded environment.

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.add()const originalAddValue = Atomics.add(sharedArray,0,10);
    console.log(Atomics.add: Original value: ${originalAddValue}, New value: ${sharedArray[0]});

    Output

    Atomics.add: Original value: 0, New value: 10
    

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.sub()const originalSubValue = Atomics.sub(sharedArray,0,5);
    console.log(Atomics.sub: Original value: ${originalSubValue}, New value: ${sharedArray[0]});

    Output

    Atomics.sub: Original value: 10, New value: 5
    

    Atomics.add()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.and()const originalAndValue = Atomics.and(sharedArray,0,0b1010);
    console.log(Atomics.and: Original value: ${originalAndValue}, New value: ${sharedArray[0].toString(2)});

    Output

    Atomics.and: Original value: 5, New value: 0
    

    Atomics.or()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.or()const originalOrValue = Atomics.or(sharedArray,0,0b1100);
    console.log(Atomics.or: Original value: ${originalOrValue}, New value: ${sharedArray[0].toString(2)});

    Output

    Atomics.or: Original value: 0, New value: 1100
    

    Atomics.xor()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.xor()const originalXorValue = Atomics.xor(sharedArray,0,0b0110);
    console.log(Atomics.xor: Original value: ${originalXorValue}, New value: ${sharedArray[0].toString(2)});

    Output

    Atomics.xor: Original value: 12, New value: 1010
    

    Atomics.load()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.load()const loadedValue = Atomics.load(sharedArray,0);
    console.log(Atomics.load: Loaded value: ${loadedValue});

    Output

    Atomics.load: Loaded value: 10
    

    Atomics.store()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.store()
    Atomics.store(sharedArray,0,42);
    console.log(Atomics.store: New value: ${sharedArray[0]});

    Output

    Atomics.store: New value: 42
    

    Atomics.exchange()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.exchange()const originalExchangeValue = Atomics.exchange(sharedArray,0,99);
    console.log(Atomics.exchange: Original value: ${originalExchangeValue}, New value: ${sharedArray[0]});

    Output

    Atomics.exchange: Original value: 42, New value: 99
    

    Atomics.compareExchange()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.compareExchange()const expectedValue =99;const newValue =55;const successfulCompareExchange = Atomics.compareExchange(sharedArray,0, expectedValue, newValue);
    console.log(Atomics.compareExchange: Operation was${successfulCompareExchange ? ' ' : ' not '}successful. New value: ${sharedArray[0]});

    Output

    Atomics.compareExchange: Operation was successful. New value: 55
    

    Atomics.wait()

    // Shared memory setupconst sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Atomics.wait()const valueToWaitFor =55;
    Atomics.store(sharedArray,0, valueToWaitFor);setTimeout(()=>{
    
    Atomics.notify(sharedArray,0);},2000);const waitResult = Atomics.wait(sharedArray,0, valueToWaitFor,5000);
    console.log(Atomics.wait: Wait result: ${waitResult});

    Output

    Atomics.wait: Wait result: timed-out
    

    Example 2: Real-World Use Case – Synchronized Counter

    In this real-world scenario, we employ the Atomics object to construct a synchronized counter; multiple threads increment this counter through the use of the Atomics.add() operation, thus guaranteeing atomicity in our update process. The functionality and necessity for effective thread coordination become evident with such an application: it offers practical data management solutions within a multi-threaded environment.

    const sharedBuffer =newSharedArrayBuffer(4);const sharedArray =newInt32Array(sharedBuffer);// Synchronized counterfunctionincrementCounter(){const incrementValue =1;const originalValue = Atomics.add(sharedArray,0, incrementValue);
      console.log(Incremented counter by ${incrementValue}. New value: ${sharedArray[0]});}// Multiple threads incrementing the countersetInterval(()=>{incrementCounter();},1000);// Simulate other activities in the main threadsetInterval(()=>{
      console.log('Main thread doing other work.');},3000);

    Output

    Incremented counter by 1. New value: 1
    Incremented counter by 1. New value: 2
    Main thread doing other work.
    Incremented counter by 1. New value: 3
    Incremented counter by 1. New value: 4
    Incremented counter by 1. New value: 5
    Main thread doing other work.
    Incremented counter by 1. New value: 6
    Incremented counter by 1. New value: 7
    Incremented counter by 1. New value: 8
    Main thread doing other work.
    ...
  • Async Iteration

    Asynchronous Iteration

    In JavaScript, asynchronous iteration refers to the ability to iterate over asynchronous sequences or collections, such as those returned by asynchronous functions or generators. Async iteration is typically used with operations that involve asynchronous tasks, such as fetching data from a remote server or reading from a file.

    Understanding Asynchronous Operations

    In basic terms, asynchronous operations in programming denote tasks or procedures that do not obstruct the program’s execution during their pending completion. Rather than pausing for each operation to conclude before proceeding onto the subsequent one; these asynchronous tasks enable a program: it continues executing other duties, concurrently waiting for the current task’s finalization.

    Using the ‘for await…of’ Loop

    The for await…of loop is used for asynchronous iteration. It works similarly to the regular for…of loop, but it is designed to work with asynchronous iterators. An asynchronous iterator is an object that defines an async next() method, which returns a promise for the next value in the sequence.

    Example: Using Promises

    JavaScript incorporates promises as a characteristic to manage asynchronous operations; these promises symbolize the potential outcomes, either completion or failure of an asynchronous task. Notably, the function asyncOperation emulates such tasks by returning a promise. The ‘for await…of’ loop elegantly navigates the asynchronous sequence, emphasizing promise utilization in managing non-blocking operations without compromising code lucidity.

    <!DOCTYPE html><html><body><h2>Async Iteration with Promises</h2><div id="output"></div><script>functionasyncOperation(value){returnnewPromise(resolve=>{setTimeout(()=>{
    
        document.getElementById('output').innerHTML +=&amp;lt;p&amp;gt;Processed: ${value}&amp;lt;/p&amp;gt;;resolve(value);},1000);});}const asyncIterable ={[Symbol.asyncIterator]:asyncfunction*(){for(let i =1; i &lt;=3; i++){yieldawaitasyncOperation(i);}},};asyncfunctionprocessAsyncIterable(){forawait(const result of asyncIterable){
      document.getElementById('output').innerHTML +=&amp;lt;p&amp;gt;Received: ${result}&amp;lt;/p&amp;gt;;}}processAsyncIterable();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 2: Using Fetch API for Asynchronous HTTP Requests

    Here, we demonstrate asynchronous iteration with the Fetch API for executing HTTP requests: The asyncIterable operates to fetch data in an asynchronous manner. Furthermore; employing a 'for await...of' loop - it elegantly traverses through results showcasing how seamlessly async iteration amalgamates with external source data retrieval.

    <!DOCTYPE html><html><body><h2>Async Iteration with Fetch API</h2><div id="output"></div><script>const url ='https://jsonplaceholder.typicode.com/todos/';const asyncIterable ={[Symbol.asyncIterator]:asyncfunction*(){for(let i =1; i <=3; i++){const response =awaitfetch(${url}${i});const data =await response.json();
    
        document.getElementById('output').innerHTML +=&amp;lt;p&amp;gt;Received: ${JSON.stringify(data)}&amp;lt;/p&amp;gt;;yield data;}},};asyncfunctionprocessAsyncIterable(){forawait(const result of asyncIterable){// Already displaying results above, no need for additional output.}}processAsyncIterable();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 3: Using callback

    The approach employs a callback-based mechanism to achieve asynchronous iteration. The function asyncOperation imitates an asynchronous task and calls back upon completion. Meanwhile, the processAsyncIterable function actively iterates through an array, invoking the asynchronous operation for every element.

    <!DOCTYPE html><html><body><h2>Async Iteration with callback</h2><div id="output"></div><script>functionasyncOperation(value, callback){setTimeout(()=>{
    
      document.getElementById('output').innerHTML +=&amp;lt;p&amp;gt;Processed: ${value}&amp;lt;/p&amp;gt;;callback(value);},1000);}functionprocessAsyncIterable(iterable, callback){const iterator = iterable[Symbol.iterator]();functioniterate(){const next = iterator.next();if(next.done){return;}const value = next.value;asyncOperation(value,result=&gt;{
        document.getElementById('output').innerHTML +=&amp;lt;p&amp;gt;Received: ${result}&amp;lt;/p&amp;gt;;iterate();});}iterate();}const asyncIterable =[5,6,7,8,9,10];processAsyncIterable(asyncIterable,result=&gt;{// You can handle final result or additional actions here if needed.});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 4: Promise With Error

    The method .then() in JavaScript employs one or two callback functions to manage the successful resolution of a Promise: upon the promise's resolution, it executes its first function; should rejection occur an optional second function is then executed.

    The method .catch() accompanies Promises, specifically to address promise rejections. A single callback function executes upon the rejection of the promise; this provides an elegant solution for managing errors in asynchronous operations - eliminating the need for a distinct .then() block dedicated to error handling.

    <!DOCTYPE html><html><head><style>
    
    #output {
      margin-top:20px;}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;h2&gt;Async Iteration with Promises&lt;/h2&gt;&lt;button onclick="startAsyncIteration()"&gt;Start Async Iteration&lt;/button&gt;&lt;div id="output"&gt;&lt;/div&gt;&lt;script&gt;functiondelay(ms){returnnewPromise(resolve=&gt;setTimeout(resolve, ms));}functionfetchData(index){returnnewPromise((resolve, reject)=&gt;{if(index &lt;5){delay(1000).then(()=&gt;resolve(Data ${index}));}else{// Simulate an error for index 5reject(newError('Error fetching data for index 5'));}});}functionstartAsyncIteration(){
    document.getElementById('output').innerHTML ='';let index =0;functioniterate(){fetchData(index).then(data=&gt;{displayData(data);
          index++;if(index &lt;6){iterate();}}).catch(error=&gt;{// Display error on the page.displayError(error.message);});}iterate();}functiondisplayData(data){const outputDiv = document.getElementById('output');
    outputDiv.innerHTML +=&amp;lt;p&amp;gt;Data received: ${data}&amp;lt;/p&amp;gt;;}functiondisplayError(errorMessage){const outputDiv = document.getElementById('output');
    outputDiv.innerHTML +=&amp;lt;p style="color: red;"&amp;gt;Error: ${errorMessage}&amp;lt;/p&amp;gt;;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Real World Use Cases

    In real-world scenarios, we apply JavaScript async iterations to optimize various asynchronous operations: fetching data concurrently from multiple APIs in web applications; processing real-time updates - a function critical for chat systems and executing batch tasks or parallel tasks that require intensive resources. Furthermore, managing file operations and streams is possible with this technique along with handling concurrent user interactions on interactive web pages. Other applications involve processing data from IoT devices dynamically loading content onto webpages, these too benefit greatly from the use of asynchronous iteration due to their need for non-blocking efficiency as well responsiveness when dealing with complex task management such as offline-first application's data synchronization.

  • Ajax

    Asynchronous JavaScript and XML (Ajax) represents a web development technique: it enables dynamic, interactive communication between server and webpage without necessitating complete page reload. The descriptor “asynchronous” underlines that data exchanges can occur in the background, independent of user experience disruption. Rather than idly awaiting full-page refreshment; Ajax empowers real-time updates on specific sections of a webpage, thus yielding an interface that is more seamless and responsive.

    How Ajax works?

    The central role in enabling dynamic updates, without the necessity of a full page reload, belongs to the XMLHttpRequest object within JavaScript’s Ajax functionality. This particular process allows for asynchronous communication between server and web page. The server responds with data, usually in JSON or XML format when receiving a request sent by this object. Processing this data is the task of JavaScript; it updates specific portions of the webpage in real-time. The asynchronous nature which is a critical feature for modern web development ensures these operations occur unobtrusively in background, thereby enhancing interactivity by allowing data to be fetched and sent asynchronously.

    Here, we will to explore Ajax to get a deeper understanding of it.

    There are 4 approaches to make Ajax calls or to implement Ajax in JavaScript and they are:

    • XMLHttpRequest (Older Approach)
    • Fetch API (Modern Approach)
    • Axios (Library for HTTP Requests)
    • jQuery Ajax

    We will be using JSONPlaceholder in all the examples for understanding purposes.

    JSONPlaceholder is an open-source and simulated REST API provider which lets developers test their prototype applications. It returns fake/dummy data for various resources like users, posts, comments etc. The API endpoints of JSONPlaceholder can be made using HTTP requests and they will be mimicking the nature of real APIs without any need for authentication. Our goal here is to use these APIs/endpoints to under Javascript-Ajax.

    Using XMLHttpRequest

    The Native JavaScript approach using XMLHttpRequest represents the oldest method for asynchronous requests. It relies on the XMLHttpRequest object to create and send HTTP requests. This method involves setting up callback functions to handle various states of the request, making it suitable for simpler scenarios. However, it has some limitations compared to more modern approaches.

    Example

    <!DOCTYPE html><html lang="en"><body><p>Native XMLHttpRequest Example</p><button onclick="nativeAjax()">Make Request</button><pre id="result"></pre><script>functionnativeAjax(){var xhr =newXMLHttpRequest();
    
    xhr.open('GET','https://jsonplaceholder.typicode.com/users/2',true);
    xhr.onreadystatechange=function(){if(xhr.readyState ==4&amp;&amp; xhr.status ==200){var responseData =JSON.stringify(JSON.parse(xhr.responseText),null,2);
        document.getElementById('result').innerText ='Native XMLHttpRequest:\n'+ responseData;}};
    xhr.send();}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Using Fetch API

    Presenting a modern alternative to XMLHttpRequest, the Fetch API offers a more straightforward and powerful syntax; it returns Promises thus enhancing the intuitive handling of asynchronous operations. Supporting an extensive array of HTTP methods and headers: this provides developers with a cleaner, concise method for making asynchronous requests. Contemporary JavaScript applications often prefer it for its clarity and ease of use.

    Example

    <!DOCTYPE html><html><body><h1>Fetch API Example</h1><button onclick="fetchApi()">Make Request</button><pre id="result"></pre><script>functionfetchApi(){fetch('https://jsonplaceholder.typicode.com/users/3').then(response=>{if(!response.ok){thrownewError('Network response was not ok');}return response.json();}).then(data=>{var formattedData =JSON.stringify(data,null,2);
    
        document.getElementById('result').innerText ='Fetch API:\n'+ formattedData;}).catch(error=&gt;{
        document.getElementById('result').innerText ='Fetch API Error: '+ error.message;});}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Using Axios

    Designed for making HTTP requests, Axios emerges as a popular JavaScript library. Its popularity is largely due to its clean and concise syntax: built on Promises; furthermore, it boasts automatic JSON data transformation support features that set it apart from other libraries in the field. Offering more than just basic functionality, Axios presents advanced features such as request and response interceptors, a robust selection for managing AJAX operations within the context of modern web development environment.

    Example

    <!DOCTYPE html><html><head><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script></head><body><h1>Axios Example</h1><button onclick="axiosExample()">Make Request</button><pre id="result3"></pre><script>functionaxiosExample(){
    
    axios.get('https://jsonplaceholder.typicode.com/users/5').then(response=&gt;{var formattedData =JSON.stringify(response.data,null,2);
        document.getElementById('result3').innerText ='Axios:\n'+ formattedData;}).catch(error=&gt;{
        document.getElementById('result3').innerText ='Axios Error: '+ error.message;});}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Using Ajax jQuery

    The $.ajax method in jQuery simplifies the AJAX request process: a popular approach previously; however, its usage has waned alongside modern JavaScript's ascent. Offering an interface that is both consistent and cross-browser compatible, jQuery Ajax remains suitable for projects already using or needing specific features of jQuery due to these advantages it presents. However, for new projects, modern alternatives may be preferred.

    Example

    <!DOCTYPE html><html><head><script src="https://code.jquery.com/jquery-3.6.4.min.js"></script></head><body><h1>jQuery Ajax Example</h1><button onclick="jqueryAjax()">Make Request</button><pre id="result4"></pre><script>functionjqueryAjax(){
    
    $.ajax({
      url:'https://jsonplaceholder.typicode.com/users/7',
      method:'GET',
      dataType:'json',success:function(data){var formattedData =JSON.stringify(data,null,2);
        document.getElementById('result4').innerText ='jQuery Ajax:\n'+ formattedData;},error:function(xhr, status, error){
        document.getElementById('result4').innerText ='jQuery Ajax Error: '+ error;}});}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Ajax Use Cases

    In real-world scenarios, developers commonly employ Ajax to create web applications that are both responsive and interactive. A pertinent example: a social media platform; here, users have the ability - thanks to Ajax, to add or load new comments in the background without needing an entire page refresh. Dynamic updating ensures a user experience that is smooth and uninterrupted, permitting individuals to engage with content and one another seamlessly. This process yields a platform more responsive and engaging; it amplifies user interaction thus enhancing satisfaction.

    Prominent companies utilizing Ajax for enhanced user experiences include Google (Gmail, Maps), Facebook, Twitter, Amazon, Netflix, GitHub, LinkedIn, YouTube, Microsoft Office Online, and Uber. Ajax is employed for real-time updates, dynamic content loading, and seamless interactions on their respective platforms.

  • Validate URLs

    In this chapter, we will learn how we can validate URLs in JavaScript. Before knowing how to validate URLs, let’s understand what a URL is.

    What is a URL?

    A URL or Uniform Resource Locator identifies web pages, images, and videos on the internet. URLs are website addresses that transfer files, send emails, and many more.

    URLs consist of a protocol, domain name, and so on. URL indicates how the browser gets the data and where to get the data.

    We use a URL in the anchor tags or buttons to navigate to another location. We must verify the URL’s validity before using it.

    Validating URLs in JavaScript

    There are ways to validate URLs in JavaScript. Let us understand the rule to validate URLs:

    Rules to validate URLs

    Below are the rules to validate URLs:

    • URL must start with http://, https://, or www.
    • URL must contain a domain name.
    • URL must contain a top-level domain like .com, .org, .net, etc.
    • URL must not contain any spaces.

    Using Regular Expression

    Regular expression are much useful in validating URLs. A regular expression describes a pattern of characters. We use these patterns to match some text.

    Syntax

    Below you can see the regular expression syntax to validate URLs:

    string.match(regExp);var pattern =newRegExp(regExp);
    pattern.test(string);

    The first syntax matches a regular expression. The second syntax tests for a URL pattern.

    Example

    In the following example, we use a regular expression to validate URLs.

    <!DOCTYPE html><html><head><title>Validate URLs in JavaScript</title></head><body><h2>Validate URLs using Regular Expression</h2><div id="output"></div><script>let output = document.getElementById("output");var url ="https://www.tutorialspoint.com";var pattern =newRegExp("^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$");if(pattern.test(url)){
       output.innerHTML ="URL is valid";}else{
       output.innerHTML ="URL is not valid";}</script></body></html>

    Using URL() Constructor

    The URL() constructor returns a newly created URL object. The constructor throws a TypeError if the base URL or resultant URL is invalid.

    Syntax

    Below is the syntax to use the URL() constructor:

    var url =newURL(urlStr);newURL(url, base);return url.protocol ==='http:'|| url.protocol ==='https:';

    The first two syntaxes create a new URL, either with or without a base. The second syntax is to check the URL protocol validity.

    Example

    In this program, the URL method validates the URLs and returns a type error in the case of invalid URLs.

    <!DOCTYPE html><html><head><title>Validate URLs in JavaScript</title></head><body><h2>Validate URLs using URL() Constructor</h2><div id="output"></div><script>let output = document.getElementById("output");try{var url =newURL("https://www.tutorialspoint.com");if(url.protocol ==='http:'|| url.protocol ==='https:'){
    
      output.innerHTML ="URL is valid";}else{
      output.innerHTML ="URL is not valid";}}catch(e){
    output.innerHTML ="URL is not valid";}</script></body></html>

    This chapter taught us two methods to validate a URL. The first method suggests using a regular expression match or a pattern test. The second method is the built-in URL method. The URL method is easy because we can avoid the test case missing in the case of regular expressions.

    Both methods are useful in validating URLs. We can use any of the methods based on our requirements.

  • Unit Testing

    Unit testing is must in software development life-cycle. It is a process in which we can test small units of code individually to ensure that they are working correctly. In JavaScript, we can use various unit testing frameworks to test our code. Unit testing help us to find bugs early in the development process. Instead of testing the whole application, we can test small units of code.

    Why Unit Testing?

    • Catch bug early : testing smaller parts of code, it becomes easy to catch bug early in the development process.
    • Easier Refactoring: With the help of unit testing, you get confidence to make changes in code, because we know the existing code you have tested is already working.
    • Improves Code Quality: Writing unit tests help us to write better code. It helps us to write modular code which is easy to test.

    Unit Testing Frameworks

    There are many unit testing frameworks are available in JavaScript. Some of them are most popular and widely used. Some of them are −

    • Jest: Jest is a JavaScript testing framework developed by Facebook. It is widely used for testing JavaScript code. Jest is fast, easy to use and it absolutely provides everything you need for testing.
    • Mocha: Mocha has many feature, It is a JavaScript test framework that run on Node.js and in the browser, and makes asynchronous testing simple and fun. Mocha tests run serially, that allow it for flexible and accurate reporting, when mapping uncaught exceptions to the correct test cases.
    • Jasmine: Jasmine is a behavior-driven development framework for testing JavaScript code. It does not rely on browsers, DOM, or any JavaScript framework. Jasmine is inspired by other testing frameworks such as ScrewUnit, JSSpec, JSpec, and RSpec.
    • QUnit: QUnit is a powerful, easy-to-use JavaScript unit testing framework. It’s used by the jQuery project to test its code and plugins but is capable of testing any generic JavaScript code.

    Structure of Unit Testing

    In common unit test cases there are a few steps those are −

    • Setup: In this part, we set up the environment for the test. We can create objects, initialize variables, etc.
    • Execute: In this part, we execute the code that we want to test.
    • Assert: In this part, we check the result of the execution. We check if the result is as expected or not.
    • Teardown: In this part, we clean up the environment after the test. We can destroy objects, clear variables, etc.

    Example of unit test using Jest

    Below is a code snippet of unit test using Jest.

    Example

    functionsum(a, b){return a + b;}
    module.exports = sum;// test.jsconst sum =require('./sum');test('adds 1 + 2 to equal 3',()=>{expect(sum(1,2)).toBe(3);});

    Output

    PASS  ./sum.test.js
       adds 1 + 2 to equal 3 (3ms)
    

    In this example, we have a function sum which takes two arguments and returns the sum of those two arguments. We have written a test case for this function to check if the function is working correctly or not.

  • Undefined Check

    When the value is absolutely not present in the variable or string or anything else, we call it as Undefined. In JavaScript, undefined is a one of the primitive data type. It is used to represent the absence of a value.

    It get assigned to a variable when it is declared but not assigned any value.

    How to check if a variable is undefined?

    There are more than one way to check if a variable is undefined or not. Let’s see them one by one.

    • Using typeof operator
    • Using strict equality operator
    • Using void operator

    Using typeof operator

    When the variable is undefined, it means the variable is not declared. Users cant use it in the if-else conditional statement like the above method.

    To check the type of the undeclared variables, we can use the typeof operator. The typeof operator takes the variable as an operand and returns the variable type. As the operand of typeof, we can use undeclared variables also.

    Syntax

    Below syntax is used to check undefined variable using the typeof operator.

    typeof variable_name ==='undefined'

    Example

    Below is the example code given, that shows how to use the typeof operator to check the undefined value of the variable.

    <html><body><script>var a;if(typeof a ==='undefined'){
    document.write('a is undefined');}</script></body></html>

    Output

    Following is the output of the above code

    a is undefined
    

    Using strict equality operator

    In this method, we will use the strict equality operator to check whether a variable is null, empty, or undefined. If we dont assign the value to the variable while declaring, the JavaScript compiler assigns it to the undefined value. So, we can check that if the variable contains the null value or undefined value, it means we have a null variable.

    Syntax

    Below is the syntax given for checking the undefined value of the variable using the strict equality operator.

    variable_name ===undefined

    Example

    <html><body><script>var a;if(a ===undefined){
    document.write('a is undefined');}</script></body></html>

    Output

    Following is the output of the above code

    a is undefined
  • Short Circuiting

    In JavaScript, short-circuiting is a feature that checks conditions and stops as soon as it knows the answer. It doesn’t look for the rest of the expression, and that prevent unnecessary evaluations.

    Short-Circuiting for && operator

    Short circuit evaluation with &&(AND) logical operator means if the first expression evaluates to false then whole expression will be false and the rest of the expressions will not be evaluated.

    Code-snippet

    Below is an example snippet of short-circuiting with the && operator.

    let x =0&&"hello";// x will be 0, as 0 is falsy and short-circuitslet y =true&&"world";// y will be "world" because the first value is truthylet z ="hello"&&"world";// z will be "world" because both values are truthy
    console.log(x);// 0
    console.log(y);// world
    console.log(z);// world

    Output

    Following is the output of the above code

    0
    world
    world
    

    Short-Circuiting for || operator

    Short circuit evaluation with ||(OR) logical operator means if the first expression evaluates to true then whole expression will be true and the rest of the expressions will not be evaluated.

    Code-snippet

    Below is an example snippet of short-circuiting with the || operator.

    let x =0||"hello";// x will be "hello" because 0 is falsylet y =true||"world";// y will be true because the first value is truthylet z ="hello"||"world";// z will be "hello" because the first value is truthy
    console.log(x);// hello
    console.log(y);// true
    console.log(z);// hello

    Output

    Following is the output of the above code

    hello
    true
    hello
    

    Short-Circuiting Assignment

    Short-circuiting can be used in assignment operations as well. Means, if you have to assign something based on a condition, you can use short-circuiting.

    Code-snippet

    Below is an example snippet of short-circuiting in assignment operations.

    let x =0;let y =10;let z = x || y;// z will be 10 because x is falsy
    console.log(z);// 10

    In above example, z will be assigned the value of y because x is falsy.

    Output

    Following is the output of the above code

    10
    

    Short-Circuiting in Function Calls

    Short-circuiting can be used in function calls as well. Means, if you have to call a function based on a condition, you can use short-circuiting.

    Code-snippet

    Below is an example snippet of short-circuiting in function calls.

    functiongreet(name){return name ||"Guest";}let x =greet("John");// x will be "John" because name is truthylet y =greet("");// y will be "Guest" because name is falsy
    console.log(x);// John
    console.log(y);// Guest

    In above example, if name is truthy, it will return the name, otherwise it will return “Guest”.

    Output

    Following is the output of the above code

    John
    Guest
  • Rest Operator

    There are times when we want to pass any number of arguments to a function or want to get specific elements separately from an array or object. In such cases, we can use the rest operator.

    What is Rest Operator?

    The rest operator () allows us to call a function with any number of arguments and then access those excess arguments as an array. The rest operator also allows us in destructuring array or objects.

    Rest Operator with Function Parameters

    When you define a function, you can use rest operator to get all remaining arguments inside an array. This process helps us to pass any number of arguments without knowing how many they are.

    Code-Snippet

    Below is an example snippet of using rest operator in function parameters. We will sum all the numbers passed to the function.

    functionsum(...args){let total =0;for(let i of args){
    
     total += i;}return total;}
    console.log(sum(1,2,3,4,5));// 15 console.log(sum(1,2,3));// 6

    Output

    15
    6
    

    Rest Operator with Array Destructuring

    If you have given an array, and if you want specific element separately and rest of the elements in a separate array, you can use rest operator.Rest operator also help us to destructure an array.

    Code-Snippet

    Below is an example snippet of using rest operator with array destructuring for getting first and second element separately and rest of the elements in a separate array.

    let arr =[1,2,3,4,5];let[first, second,...rest]= arr;
    
    console.log(first);// 1
    console.log(second);// 2
    console.log(rest);// [3, 4, 5]

    Output

    1
    2
    [3, 4, 5]
    

    Rest Operator with Object Destructuring

    Now, if you want specific properties separately and rest of the properties in a separate object, you can use rest operator for achieving that. Rest operator also help us to destructure an object.

    Code-Snippet

    Below is an example snippet of using rest operator with object destructuring for having first and second property separately and rest of the properties in a separate object.

    let obj ={ name:"Aish", age:21, city:"Hyderabad", country:"India"};let{ name, age,...rest }= obj;
    
    console.log(name);//  Aish
    console.log(age);// 21
    console.log(rest);// { city: "Hyderabad", country: "India" }

    Output

    Aish
    21
    { city: "Hyderabad", country: "India" }
  • Reduce Method

    What is Reduce Method?

    In JavaScript, Reduce method is used to manipulate array. This method executes a reducer function on each element of the array (from left to right) and returns a ‘single value’ as a result.

    It accepts an optional parameter named ‘initialValue’. If we do not pass this parameter to the method, it will consider the arr[0] value as the initial value. Additionally, it will execute the callback function on the passed initialValue parameter.

    This method does not execute the reducer function for empty array elements. In addition to that, it does not modify the original array.

    Note : If the current array is empty or doesn’t contain any initialValue, this method will throw a ‘TypeError’ exception.

    Syntax

    Following is the syntax of JavaScript Array.reduce() method

    reduce(callbackFn(accumulator, currentValue, currentIndex, array), initialValue)

    Parameters

    The reduce() function has two parameters which are callbackfn() and initialValue. They are described below in detail.

    • initialValue (optional): The value to which the accumulator parameter is initialized when the first time the callback function is called.
    • callbackFn: This is the function that executes on each element in the array.

    The callbackFn() function in turn takes four arguments They are –

    • accumulator: This is the current element being processed in the array. If the initialValue is specified, its value will be arr[0], if not its value will be arr[1].
    • currentValue: It refers to the current element.
    • currentIndex (optional): This is the index of the current element being processed in the array.
    • array (optional): This is the array on which the reduce() method is called.

    Return Value

    This method returns the single value that is the result after reducing the array.

    Example

    In the following example, we are using the JavaScript Array.reduce() method to sum all the elements present in the provided array.

    <html><body><script>const number =[10,20,30,40,50];const sum = number.reduce((accumulator, currentValue)=> accumulator + currentValue,0);
    document.write(sum);</script></body></html>

    The accumulator starts at 0, and for each element in the array, it adds the current element to the accumulator. The final result of the accumulator (150) is the sum of all the elements.

    Output

    Following is the output of the above code

    150
    

    Example

    If the current array does not contain any element(no initial value available), the reduce() method will throw a “TypeError” exception

    <html><body><script>const numbers =[];try{
    
      numbers.reduce((accumulator, currentValue)=&gt; accumulator * currentValue);}catch(error){
      document.write(error);}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Following is the output of the above code

    TypeError: Reduce of empty array with no initial value
    

    Reduce method on TypedArray

    We can use reduce method on TypedArray as well. Everything is similar to normal array, means we can process and combine elements in same way as we do with arrays.

    Syntax

    Following is the syntax of JavaScript TypedArray reduce() method

    TypedArray.reduce(callbackFn(accumulator, currentValue, currentIndex, array), initialValue)

    Example

    The product of all elements within a typed array.

    In the following example, we are using the JavaScript TypedArray reduce() method to execute the user-provided function named multi() on each element of this typed array [1, 2, 3, 4, 5]. The multi() function multiplies all the elements within the current typed array.

    <html><head>
    JavaScript TypedArray reduce() Method
    </head><body><script>//functionfunctionmulti(accumulator, currentValue){return accumulator * currentValue;}const T_array =newUint16Array([1,2,3,4,5]);
    document.write("Typed array: ", T_array);//Using the reduce() method
    document.write("<br>The product of typed array elements: ", T_array.reduce(multi));</script></body></html>

    Output

    Following is the output of the above code

    Typed array: 1,2,3,4,5
    The product of typed array elements: 120
    

    Example

    If the current typed array does not contain any element(no initial value available), the reduce() method will throw a "TypeError" exception.

    In the given example below, we use the JavaScript TypedArray reduce() method to execute the user-provided reducer callback function named "ArrowFunction" on each element of this empty typed array ([]).

    <html><head><title>JavaScript TypedArray reduce() Method</title></head><body><script>const T2_array =newUint16Array([]);//empty typed array
    document.write("Length of the typed array: ", T2_array.length);//using the reduce methodtry{
       T2_array.reduce((a, b)=> a + b);}catch(error){
    
    document.write("&lt;br&gt;", error);}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Following is the output of the above code

    Length of the typed array: 0
    TypeError: Reduce of empty array with no initial value
    

    Reduce method on Map

    We can use reduce method on Map as well. Everything is similar to normal array, means we can process and combine elements in same way as we do with arrays.

    Syntax

    Following is the syntax of JavaScript Map reduce() method

    Map.reduce(callbackFn(accumulator, currentValue, currentIndex, array), initialValue)

    Example

    The sum of all elements within a Map.

    In the following example, we are using the JavaScript Map reduce() method to execute the user-provided function named add() on each element of this map. The add() function adds all the elements within the current map.

    <html><head><title>JavaScript Map reduce() Method</title></head><body><script>//functionfunctionadd(accumulator, currentValue){return accumulator + currentValue;}const map =newMap([[1,2],[3,4],[5,6]]);
    document.write("Map: ", map);//using the reduce() method
    document.write("<br>The sum of map elements: ",[...map.values()].reduce(add));</script></body></html>

    Output

    Following is the output of the above code

    Map: 1 => 2,3 => 4,5 => 6
    The sum of map elements: 12