Blog

  • JavaScript – Engine and Runtime

    A JavaScript engine is a computer software that executes JavaScript code. It is responsible for translating human-readable JavaScript code into instructions that the hardware of the computer can understand.

    When JavaScript code is executed in a browser, it does not make direct contact with your computer’s hardware. Rather, it communicates with the JavaScript engine, which acts as an interface between the system and your code.

    Google’s v8 Engine is the most used JS engine, even though each browser has its own. This v8 Engine powers Node.js, which is used to build server-side applications, and Google Chrome.

    In this chapter you will learn more about what a JS engine is and how it functions −

    How JavaScript Engine Works?

    A call stack and a heap are always present in any JS engine. With the help of the execution context, our code is run in the call stack. Also, the heap is an unstructured memory pool that houses every item our application needs.

    JavaScript Engine Working

    Now that you know where the code is executed, the next step is to find out how to compile it into machine code so that it can run later. But let’s first review the compilation and interpretation.

    Compilation vs Interpretation

    During compilation, all of the code is concurrently transformed into machine code and stored in a binary file that a computer can run.

    Line by line the source code is executed by the interpreter during interpretation. While the program is running, the code still needs to be transformed into machine code, but this time it is done line by line.

    In the past, JS was only an interpreted language. But “just-in-time” compilation, a combination of compilation and interpretation, is now used by the contemporary JS engine.

    When using JIT compilation all of the code is concurrently translated into machine code and run immediately.

    You are possibly curious about the difference between JIT and compilation. One notable distinction is that the machine code is saved in a portable file after compilation. There is no need to rush after the compilation process; you can run it whenever you like.

    However, when JIT is used, the machine code must be executed as soon as the compilation process is completed.

    JIT and JavaScript

    Let us look at how JIT works specifically in JavaScript.

    So, when a piece of JavaScript code enters the engine, the first step is to parse it.

    During the parsing process, the code is converted into a data structure known as the AST or Abstract Syntax Tree. This works by first breaking down each line of code into bits that are significant to the language (e.g. as the const or function keywords), and then saving all of these pieces into the tree in a structured manner.

    This phase also determines whether there are any syntax mistakes. The generated tree is then used to generate machine code.

    JIT in JavaScript

    The next stage is compilation. The engine takes the AST and compiles it into machine code. The machine code is then performed promptly because JIT is used; keep in mind that this execution occurs on the call stack.

    But it’s not the end. The contemporary JavaScript engine generates wasteful machine code in order to run the program as fast as possible. The engine then takes the pre-compiled code, optimizes and re-compiles it while the program is already running. All this optimizing happens in the background.

    So far, you have learnt about the JS Engine and how it works behind the scenes. Let us take a look at what a JavaScript runtime is, more especially the browser runtime.

    List of JavaScript Engines

    Here is the list of available JavaScript Engines −

    BrowserName of Javascript Engine
    Google ChromeV8
    Edge (Internet Explorer)Chakra
    Mozilla FirefoxSpider Monkey
    SafariJavascript Core Webkit

    Let us understand each engine mentioned in the above table in brief −

    • V8: Developed by Google for Chrome. It improves the user experience on websites and applications by accelerating JavaScript execution. Also, V8 manages memory by collecting superfluous information and makes it easier to use JavaScript on servers, like in Node.js.
    • Chakra: Chakra was created by Microsoft for Internet Explorer. It speeds up JavaScript and lets the browser do other things at the same time by running scripts on a separate CPU core.
    • SpiderMonkey: Brendan Eich at Netscape developed the first JavaScript engine, SpiderMonkey, which is currently maintains Mozilla for Firefox. Anyone can use or modify it because it is open-source.
    • WebKit: WebKit for Safari was developed by Apple and is used by iOS devices, Kindles and PlayStations. WebKit manages common browser features like history and back-and-forth navigation in addition to displaying webpages.

    What is a JavaScript Runtime?

    A JavaScript (JS) runtime is a full environment for executing JavaScript code. It is made up of a number of components that work together to help JavaScript applications run smoothly. When we talk about a JS runtime, we often mean the full ecosystem that goes beyond just executing code.

    Depending on where JavaScript is executed (in the web browser or on the server with Node.js), the runtime may include additional environment-specific features. For example, in a browser, there can be functionality for managing browser events, accessing the DOM and interfacing with browser-specific functionalities.

    For the time being, we will only cover the JavaScript runtime in the browser. Consider a JS runtime to be a large box containing all of the components required to run JavaScript in browser.

    The JS engine is at the heart of any JS runtime. However, the engine alone is not sufficient. Web APIs are required for good functionality.

    JS runtimes, particularly those used in web browsers, include Web APIs that extend the fundamental JavaScript language’s capabilities. These APIs include interactions with the Document Object Model (DOM), XMLHttpRequest (for sending HTTP requests), timers, and more.

    Web APIs extend JavaScript’s capabilities by allowing it to interact with the browser environment and perform activities like changing web-page structure, handling user events and sending network requests.

    So, basically, Web APIs are engine-provided features that are not part of the JavaScript language. JavaScript gains access to these APIs via the window object.

    JS Runtime in the Browser

    Asynchronous actions in JavaScript, like receiving user input or performing network queries, make use of callback functions. These routines are placed in the callback queue and await execution. The callback queue manages asynchronous tasks in an ordered manner.

    To react to specific events, we can attach event handler methods to DOM events like buttons. These event handler functions are also known as callback functions. So, when the click event occurs, the callback function will be called.

  • JavaScript – Design Patterns

    In JavaScript, design patterns are classes and communicating objects that are designed to deal with a general design problem in a specific setting. Generic, reusable solutions to typical issues that come up throughout software design and development are known as software design patterns.

    They give developers a forum to discuss successful design concepts and function as best practices for resolving particular kinds of problems.

    What are Design Patterns?

    A design pattern in software engineering is a generic, replicable fix for a typical problem in program design. The design is not complete enough to be coded right away. It is a description or model for problem-solving that can be used in various contexts.

    Types of Software Design Patterns

    In JavaScript, there are primarily three categories of design patterns namely −

    • Creational Design Patterns
    • Structural Design Patterns
    • Behavioral Design Patterns

    Let’s discuss them one by one −

    Creational Design Patterns in JavaScript

    In software development, creational design patterns are a subset of design patterns. They work on the object generation process, trying to make it more flexible and efficient. It maintains the independence of the system and the composition, representation, and creation of its objects.

    Singleton Pattern

    The singleton design pattern makes sure a class has only one immutable instance. In simple terms, the singleton pattern is an object that cannot be changed or replicated. It is often useful when we want an immutable single point of truth for our application.

    Suppose that we want to have a single object that has all of our application’s configuration. We also want to make it prohibit to copy or modify that object.

    Two ways to implement this pattern are using classes and object literals −

    const Settings ={initialize:()=> console.log('Application is now running'),refresh:()=> console.log('Application data has been refreshed'),}// Freeze the object to prevent modifications
    Object.freeze(Settings)// "Application is now running"
    Settings.initialize()// "Application data has been refreshed"
    Settings.refresh()// Trying to add a new key
    Settings.version ="1.0" 
    console.log(Settings)

    This will generate the below result −

    Application is now running
    Application data has been refreshed
    { initialize: [Function: initialize], refresh: [Function: refresh] }
    
    classSettings{constructor(){}launch(){ console.log('Application is now running')}refresh(){ console.log('Application data has been refreshed')}}const appInstance =newSettings()
    Object.freeze(appInstance)// "Application is now running"
    appInstance.launch()// "Application data has been refreshed"
    appInstance.refresh()

    Output

    Here is the outcome of the above code −

    Application is now running
    Application data has been refreshed
    

    Factory Method Pattern

    The Factory method pattern provides an interface for creating objects that can be modified after they are generated. By combining the logic for building our objects in a single place, this reduces and enhances the organization of our code.

    This often used pattern can be implemented in two ways: by using classes or factory functions, which are methods that return an object.

    classCreature{constructor(name, message){this.name = name
          this.message = message
          this.type ="creature"}fly=()=> console.log("Whoooosh!!")speak=()=> console.log(this.message)}const creature1 =newCreature("Zee","Hello! I'm Zee from outer space!")
    console.log(creature1.name)// output: "Zee"

    This will produce the below output −

    Zee
    

    Abstract Factory Pattern

    Without knowing the precise types of linked objects, we can use the Abstract Factory design to generate groups of them. This is useful when we need to build unique objects that share only a few characteristics.

    It works like this: a primary abstract factory connects with the client, or user. This abstract factory then uses some logic to invoke a specific factory to generate the actual object. As a result, it acts as an overlay over the typical factory layout, allowing us to produce a large range of items in a single primary factory.

    For example, we are able to develop a system for an automobile manufacturer that includes trucks, motorcycles, and cars. The Abstract Factory pattern, which handles several object types with a single primary factory, makes this easy for us to do.

    // Each class represents a specific type of vehicleclassCar{constructor(){this.type ="Car"this.wheels =4}startEngine=()=> console.log("Vroom Vroom!")}classTruck{constructor(){this.type ="Truck"this.wheels =8}startEngine=()=> console.log("Rumble Rumble!")}classMotorcycle{constructor(){this.type ="Motorcycle"this.wheels =2}startEngine=()=> console.log("Zoom Zoom!")}const vehicleFactory ={createVehicle:function(vehicleType){switch(vehicleType){case"car":returnnewCar()case"truck":returnnewTruck()case"motorcycle":returnnewMotorcycle()default:returnnull}}}const car = vehicleFactory.createVehicle("car")const truck = vehicleFactory.createVehicle("truck")const motorcycle = vehicleFactory.createVehicle("motorcycle") 
    
    console.log(car.type)
    car.startEngine()
    
    console.log(truck.type) 
    truck.startEngine() 
    
    console.log(motorcycle.type)
    motorcycle.startEngine()

    Output

    This will generate the below result −

    Car
    Vroom Vroom!
    Truck
    Rumble Rumble!
    Motorcycle
    Zoom Zoom!
    

    Builder Pattern

    The Builder pattern is used to generate objects in “steps”. Functions or methods that add particular attributes or methods are typically included in our object.

    Because it separates the development of methods and attributes into separate entities, this design is cool.

    The object we create will always contain every property and method defined by a class or factory function. Using the builder pattern, which enables us to construct an object and apply only the “steps” that are required, provides a more flexible approach.

    // Define our creaturesconst creature1 ={
       name:"Buzz Lightwing",
       message:"You'll never debug me!"}const creature2 ={
       name:"Sneaky Bugsworth",
       message:"Can't catch me! Ha ha!"}// These functions add abilities to an objectconstenableFlying=obj=>{
       obj.fly=()=> console.log(`${obj.name} has taken flight!`)}constenableSpeaking=obj=>{
       obj.speak=()=> console.log(`${obj.name} says: "${obj.message}"`)}// Add abilities to the creaturesenableFlying(creature1)
    creature1.fly()enableSpeaking(creature2)
    creature2.speak()

    Output

    This will give the following result −

    Buzz Lightwing has taken flight!
    Sneaky Bugsworth says: "Can't catch me! Ha ha!"
    

    Prototype Pattern

    By using another object as a blueprint and inheriting its properties and methods, you can create an object using the prototype pattern.

    Prototypal inheritance and how JavaScript handles it are likely familiar to you if you have been using JavaScript for a time.

    As methods and properties can be shared between objects without depend on the same class, the final result is much more flexible than what we obtain when we use classes.

    // Define a prototype objectconst creatureAbilities ={attack:()=> console.log("Zap! Zap!"),escape:()=> console.log("Soaring through the sky!")}// Create a new creature const creature1 ={
       name:"Winged Buzz",
       message:"You can't debug me!"}// Set the prototype
    Object.setPrototypeOf(creature1, creatureAbilities)// Confirm that the prototype is set successfully
    console.log(Object.getPrototypeOf(creature1)) 
    
    console.log(creature1.message) 
    console.log(creature1.attack()) 
    console.log(creature1.escape())

    Output

    This will produce the following outcome −

    { attack: [Function: attack], escape: [Function: escape] }
    You can't debug me!
    Zap! Zap!
    undefined
    Soaring through the sky!
    undefined
    

    Structural Design Patterns in JavaScript

    In software development, structural design patterns are a subset of design patterns that focus on how classes or objects are put together to create complex, larger structures. In order to increase a software system’s flexibility, re-usability, and maintainability, they help in the organization and management of relationships between objects.

    Adapter Pattern

    The Adapter Method is a structural design pattern which helps you to connect the gap between two incompatible interfaces and make them operate together.

    Let us see an example below −

    // Array of cities with population in millionsconst citiesPopulationInMillions =[{ city:"Mumbai", population:12.5},{ city:"Delhi", population:19.0},{ city:"Bangalore", population:8.4},{ city:"Kolkata", population:4.5},]// The new city we want to addconst Chennai ={
       city:"Chennai",
       population:7000000}consttoMillionsAdapter=city=>{ city.population =parseFloat((city.population /1000000).toFixed(1))}toMillionsAdapter(Chennai)// We add the new city to the array
    citiesPopulationInMillions.push(Chennai)// This function returns the largest population number constCityWithMostPopulation=()=>{return Math.max(...citiesPopulationInMillions.map(city=> city.population))}
    
    console.log(CityWithMostPopulation())

    Output

    This will generate the below result −

    19
    

    Decorator Pattern

    The decorator method is a structural design pattern that enables the addition of static or dynamic functionality to particular objects without changing how other objects of the same class behave.

    Following is the simple demonstration of this Reactivity Pattern −

    // Base class for a CarclassCar{constructor(){this.description ="Basic Car";}getDescription(){returnthis.description;}cost(){// Base price  return10000;}}// Decorator to add air conditioningclassAirConditioningDecorator{constructor(car){this.car = car;}getDescription(){returnthis.car.getDescription()+" + Air Conditioning";}cost(){// Adds cost for air conditioning  returnthis.car.cost()+1500;}}// Decorator to add a sunroofclassSunroofDecorator{constructor(car){this.car = car;}getDescription(){returnthis.car.getDescription()+" + Sunroof";}cost(){returnthis.car.cost()+2000;}}// Create a basic carconst myCar =newCar();
    console.log(myCar.getDescription()); 
    console.log(`Cost: $${myCar.cost()}`);// Add air conditioning featureconst myCarWithAC =newAirConditioningDecorator(myCar);
    console.log(myCarWithAC.getDescription()); 
    console.log(`Cost: $${myCarWithAC.cost()}`);// Add sunroof feature to the car const myCarWithACAndSunroof =newSunroofDecorator(myCarWithAC);
    console.log(myCarWithACAndSunroof.getDescription()); 
    console.log(`Cost: $${myCarWithACAndSunroof.cost()}`);

    Output

    This will generate the below result −

    Basic Car
    Cost: $10000
    Basic Car + Air Conditioning
    Cost: $11500
    Basic Car + Air Conditioning + Sunroof
    Cost: $13500
    

    Facade Pattern

    The Facade Method is a structural design pattern that improves client interaction with a subsystem by offering a higher-level, simplified interface to a group of interfaces within that subsystem.

    To make it simpler to interface with a subsystem containing multiple complex parts in an automobile, we want to create a CarFacade class. The client should only use the CarFacade class; it should not use the individual components.

    // Subsystem classesclassEngine{start(){
         console.log("Engine started!");}stop(){
         console.log("Engine stopped!");}}classTransmission{shiftGear(){
         console.log("Transmission shifted!");}}classAirConditioning{turnOn(){
         console.log("Air conditioning is ON.");}turnOff(){
         console.log("Air conditioning is OFF.");}}// Facade classclassCarFacade{constructor(){this.engine =newEngine();this.transmission =newTransmission();this.airConditioning =newAirConditioning();}startCar(){
         console.log("Starting the car...");this.engine.start();this.transmission.shiftGear();this.airConditioning.turnOn();}stopCar(){
         console.log("Stopping the car...");this.airConditioning.turnOff();this.transmission.shiftGear();this.engine.stop();}}// Client code using the Facade patternconst myCar =newCarFacade();// Starting the car
    myCar.startCar();// Stopping the car 
    myCar.stopCar();

    Output

    This will generate the below result −

    Starting the car...
    Engine started!
    Transmission shifted!
    Air conditioning is ON.
    Stopping the car...
    Air conditioning is OFF.
    Transmission shifted!
    Engine stopped!
    

    Proxy Pattern

    The Proxy Method is a structural design pattern that allows you to create an object substitute that can control access to the real object or serve as an intermediate.

    // Real objectclassRealImage{constructor(filename){this.filename = filename;this.load();}load(){
         console.log(`Loading image: ${this.filename}`);}display(){
         console.log(`Displaying image: ${this.filename}`);}}// Proxy classclassProxyImage{constructor(filename){this.filename = filename;// Real image is only loaded when neededthis.realImage =null;}load(){if(!this.realImage){// Lazy load   this.realImage =newRealImage(this.filename);}}display(){// Ensure the real image is loaded before displaying it  this.load();this.realImage.display();}}// Client codeconst image1 =newProxyImage("image1.jpg");const image2 =newProxyImage("image2.jpg");// Image is not loaded yet
    image1.display();// Image is already loaded
    image1.display();// A different image is loaded
    image2.display();

    Output

    This will lead to the below result −

    Loading image: image1.jpg
    Displaying image: image1.jpg
    Displaying image: image1.jpg
    Loading image: image2.jpg
    Displaying image: image2.jpg
    

    Behavioral Design Patterns in JavaScript

    Behavioral design patterns are a subset of software development design patterns that focus on the interactions and communication between classes and objects. They focus on how classes and objects work together and communicate in order to fulfill responsibilities.

    Chain of Responsibility Pattern

    The Chain of Responsibility is used to route requests via a number of handlers. Each handler decides whether to process the request or pass it on to the next handler in the chain.

    We could use the same example as before for this pattern because middlewares in Express are handlers that either execute a request or forward it to the next handler.

    Iterator Pattern

    The iterator can be used to navigate over the elements of a collection. This can appear unimportant in today’s computer languages, but it used to be that way.

    Any of the built-in JavaScript functions that let us iterate across data structures (for, forEach, for…of, for…in, map, reduce, filter, and so on) can use the iterator pattern.

    As with any traversal technique, we write code to iterate through data with advanced structures such as trees or graphs.

    Observer Pattern

    The observer pattern allows you to create a subscription mechanism that notifies multiple items about any changes to the item being observed. Basically, the rule is like having an event listener on a specific object, and when that object does the action we are looking for, we do something.

    React’s useEffect hook could be an excellent example here. UseEffect executes a provided function at the time it is declared.

    The hook is separated into two parts: the executable function and an array of dependents. If the array is empty, like in the example below, the function is called every time the component is shown.

    useEffect(()=>{ console.log('The component has  been rendered')},[])

    If we declare any variables in the dependency array, the function will only run when they change.

    useEffect(()=>{ console.log('var1 has been changed')},[var1])

    Even simple JavaScript event listeners can be considered as observers. This approach is also illustrated by reactive programming and tools like RxJS, which manage asynchronous information and events across systems.

  • JavaScript – Dead Zone

    What is a Dead Zone?

    A dead zone in JavaScript is a point during code execution where a variable exists but cannot be accessed.

    This is because of the behavior of variable hoisting, a mechanism that moves variable declarations to the top of their scope during compilation while leaving assignments intact.

    Dead Zones (DZs) are most commonly seen when variables are declared with let and const. Let and const declarations are block scoped which means they can only be accessed within the brackets around them. Variables on the other hand are not restricted in this way.

    How it works?

    JavaScript code executes in two phases:

    • Declaration Phase: During the declaration phase, all variables declared with var, let or const are initialized. Only var variables are initialized (set to undefined) but let and const are in a “temporal dead zone” until their actual value is assigned.
    • Execution Phase: The execution phase consists of setting values to variables and running code line by line.

    If you try to use a let or const variable before its value has been assigned, you will receive a runtime error.

    Variable Hoisting and Dead Zones

    Here is the example below −

    console.log(x);// This will give an error: "Cannot access 'x' before initialization"let x =5;

    When the console.log(x) command is executed the let variable x is declared but not initialized. So it is in the “dead zone,” and trying to use it results in an error.

    This does not apply to var variables which are automatically initialized with undefined during the declaration process.

    This happens due to the fact that variable x declaration is moved to the top of the scope, its initialization stays in its original location. So, there is a period between hoisting and actual initialization during which accessing the variable gives an error.

    Dead Zones with let and const

    Variables declared using let and const are hoisted differently from those declared with var. And var is hoisted and initialized with undefined, let and const stay uninitialized during the procedure. This behavior results in dead zones with these variable declarations.

    console.log(x);// Output: undefinedvar x =42;

    In this case, using var, x is hoisted and initialized with undefined, allowing it to be accessed before assignment. But if we replace the function by let or const:

    console.log(x);// Output: ReferenceError: Cannot access 'x' before initializationlet x =42;

    Using let, x is hoisted but not initialized. Trying to access it before initialization generates a ReferenceError, showing a dead zone.

    Dead Zones with var

    While var declarations in JavaScript behave differently than let and const declarations they can nevertheless produce dead zone refers to if not used properly.

    Understanding how var behaves during hoisting and scoping is critical for accurately detecting and managing dead zones.

    Variables declared with var are hoisted differently than let and const. With var both the declaration and the initialization are moved to the top of the scope. However, all over the hoisting phase, the variable remains undefined.

    Let us see this behavior using the below example −

    console.log(x);// Output: undefinedvar x =42;

    In this situation, x is elevated to the top of the scope and its declaration is set to undefined.

    As a result, attempting to use x before its actual assignment returns undefined rather than a ReferenceError, as let and const do.

    Handling of Dead Zones

    To avoid finding dead zones in your code, use following practices −

    • Declare Variables Before Use:- To avoid dead zones always declare variables at the beginning of their scope.
    • Understand Block Scope: Variables declared with let and const are block scoped which means they can only be accessible within the block in which they were defined. Understanding block scope allows you to manage variables more efficiently.
    • Use var with caution: While var rarely causes dead zones it does have different scoping limitations than let and const. Use var with caution and knowledge.
    • Use coding linters: Many coding linters can detect potential dead zone issues in your code helping you to catch them early in the development process.

    Benefits of reducing Dead Zones

    Identifying and decreasing dead zones in your JavaScript code can result in a number of advantages that increase overall code quality and maintainability −

    • Preventing Unexpected Problems: Eliminating dead zones reduces the possibility of having ReferenceErrors or other unexpected runtime issues, resulting in more predictable code behavior and better performance.
    • Improving Code Readability: Code without dead zones is easier to understand and maintain because developers can easily think about variable scope and initialization throughout the code-base. This improves readability and reduces cognitive stress when analyzing or altering the code.
    • Increasing Debugging Efficiency: With less dead zones, debugging becomes easier because developers can focus on actual issues rather than chasing down failures caused by uninitialized variables or incorrect variable access.
    • Collaboration: Clean, dead zone-free code promotes team collaboration by removing the chance of misunderstandings or misinterpretations about variable scoping and initialization. This promotes efficient code reviews and the smoother integration of changes into the code-base.
  • JavaScript – Data Analysis

    Data analysis is essential for modern research and business. It offers information to support innovation, strategy development, and decision-making. Computer languages like Python and R which are known for their vast libraries and statistical capabilities, have historically been linked to data analysis.

    However JavaScript is best known for web development and is gradually gaining popularity in data analysis. This chapter covers the use of JavaScript in data analysis, concentrating on its capabilities, tools and conditions where it can be used effectively.

    Introduction to Data Analysis with JS

    JavaScript’s importance in data analysis has grown considerably as a result of the development of advanced tools and frameworks for statistical calculation, data visualization and large dataset management.

    Whether you are focusing on client-side analytics, server-side computations or data visualization for web apps, JavaScript provides excellent options.

    Data Analysis Libraries in JS

    Below are some libraries listed used to data analysis in JavaScript −

    D3.js (Data-Driven Documents)

    D3.js is an advanced framework for creating rich, interactive data visualizations based on web standards. It allows developers to link any kind of data to the Document Object Model (DOM) and perform data-driven transformations on the document.

    D3.js’ flexibility and large capacity make it a popular choice for developing custom visualizations that properly show complex datasets.

    Chart.js

    Chart.js is a simple and versatile framework for making responsive charts. It supports a variety of chart formats, like line, bar, radar, doughnut and pie charts, which makes it suitable for a wide range of data visualization applications.

    Chart.js’s simplicity of use and compatibility with modern web frameworks make it a popular choice among developers wanting to quickly add interactive charts to their apps.

    Plotly.js

    Plotly.js is a high-level, declarative charting framework based on D3.js and stack.gl. It supports a variety of chart styles and provides major customization possibilities.

    Plotly.js is well-known for its ability to generate scientific and financial charts, as well as its support for 3D visualization and geographic mapping.

    Node.js and Express

    Node.js’ asynchronous, event-driven architecture makes it perfect for data-intensive applications. When combined with Express, a basic and versatile Node.js web application framework, it can be an effective tool for developing APIs and data processing pipelines.

    Node.js is able to handle massive amounts of data, making it an excellent choice for back-end data processing.

    TensorFlow.js

    TensorFlow.js is a library that allows you to create and train machine learning models directly in the browser or with Node.

    It extends TensorFlow’s capability to JavaScript which is allowing developers to build and run machine learning models without moving to a new programming environment.

    This allows for the easy integration of powerful data analysis and machine learning capabilities into JavaScript applications.

    Strengths of JavaScript in Data Analysis

    Here are some of the strengths listed below of JavaScript in data analysis −

    Ubiquity and Accessibility

    One of the most significant advantages of JavaScript is that it is used widely.

    JavaScript is the foundation of web development and all modern browsers support it, making it very easy to use.

    Because of its widespread availability, JavaScript code can be executed by anybody with a web browser, making it an excellent choice for interactive and web-based data visualization and analysis applications.

    Integration with Web Technologies

    JavaScript’s easy integration with HTML, CSS, and other web technologies allows the creation of complex, dynamic data visualizations.

    This connection is used by libraries like D3.js, Chart.js, and Plotly.js to generate dynamic charts and graphs that can be included directly in web pages.

    This feature is extremely useful in displaying data analysis results in a readable and accessible format.

    Event-Driven Programming

    JavaScript is a great tool for working with real-time data because of its event-driven nature. This is particularly helpful for tasks that involve ongoing data streams, like tracking social media trends, keeping an eye on financial markets, or analyzing Internet of Things devices.

    JavaScript can effectively manage and visualize live data and providing timely insights and allowing quick decisions.

    How to Find the Average with JavaScript?

    Finding the highest and lowest values in a dataset is an important step in data analysis. JavaScript has a variety of methods for accomplishing this, which are very helpful when manipulating and analyzing data. In JavaScript the average of a collection of integers is calculated by adding all of the values and dividing by their count.

    Data Analysis Context

    Finding the maximum and minimum values is usually considered one of the first steps in analyzing a dataset. It helps in understanding the range and distribution of data, identifying outliers and explaining key statistical concepts.

    Practical Applications

    Here are some practical applications listed below −

    • Descriptive statistics analyzes data by determining the range (difference between maximum and minimum values).
    • Data cleaning consists of detecting outliers that must be addressed.
    • Data visualization needs changing sizes and limits on charts and graphs to correctly represent data.

    Example

    Here is the findAverage function with a different example −

    functionfindAverage(arr){let sum = arr.reduce((acc, val)=> acc + val,0);return sum / arr.length;}// Driver Codelet numbers =[12,18,24,30,36];let average =findAverage(numbers);
    console.log("Average:", average);

    Output

    This will produce the below result −

    Average: 24
    

    Find the Maximum and Minimum with JavaScript

    To find the maximum and minimum values in an array in JavaScript, use the Math.max() and Math.min() functions, as well as the spread operator (…) for arrays.

    Data Analysis Context for Maximum and Minimum Values

    In data analysis finding the maximum and minimum values in a dataset is significant for a variety of reasons −

    • Range Calculation: The range represents the difference between the maximum and least values. It provides a basic measure of the distribution of the data.For the dataset [5, 12, 8, 130, 44] the range is 130 – 5 = 125.
    • Identifying Outliers: Outliers are values that differ completely from the remainder of the dataset. Knowing the maximum and minimum values helps you identify these anomalies.In the dataset [5, 12, 8, 130, 44] 130 is possibly an outlier.
    • Setting Data Boundaries: When visualizing data having the minimum and maximum values helps in determining the scale of axes for charts and graphs.For example, in a bar chart, setting the y-axis from 0 to 130 guarantees that all data points are visible.
    • Data Summary and Descriptive Statistics: Maximum and minimum values are important for summary statistics, as they provide a fast snapshot of the dataset’s distribution.Descriptive statistics like mean, median and mode are often added by minimum and maximum values to provide context.

    Example

    Below example shows the implementation of the above explanation.

    functionfindMax(arr){return Math.max(...arr);}functionfindMin(arr){return Math.min(...arr);}// Examplelet numbers =[42,7,29,83,56];let max =findMax(numbers);let min =findMin(numbers); 
    console.log("Maximum:", max);
    console.log("Minimum:", min);

    Output

    This will generate the below output −

    Maximum: 83
    Minimum: 7
    

    Summary

    JavaScript has grown into a powerful language for data analysis, with modules and tools that help everything from basic statistical computations to complex machine learning tasks and interactive data visualizations.

  • JavaScript – CORS Handling

    Cross-Origin Resource Sharing (CORS) is a browser-level security feature that, by default, blocks queries across different origins, like a front-end client querying a back-end server hosted on a separate origin or domain.

    We can use a variety of strategies to avoid or enable cross-origin queries. In this chapter, we will use code examples to demonstrate how to handle CORS in JavaScript.

    What Is CORS?

    CORS is a security feature in web browsers which is used to prevent malicious sites from making unwanted requests to other domains. It maintains the same-origin policy, which prevents web pages from sending requests to domains other than those that served the page. CORS enables servers to specify who can access their resources.

    Importance of CORS

    CORS is important for security, however it might be difficult during web development and API use. Developers deal with problems while trying to access resources from many domains. Let us examine these common issues and their solutions.

    CORS Handling using Express server

    In this method, we will develop and use NodeJS and ExpressJS servers to handle CORS requests. To accept requests from any origin, we can add the “Access-Control-Allow-Origin” header to each response object header.

    Example

    First you need to install the necessary packages for the application by using the below steps −

    npm init -y
    npm i express
    

    Create the index.js file: Create the index.js file and set up the express server. Allow the “Access-Control-Allow-Origin” response header to be delivered for all requests to the same file.

    const express =require('express');const server =express();
    
    server.use((request, response, proceed)=>{
       response.header('Access-Control-Allow-Origin','*');
       response.header('Access-Control-Allow-Methods','GET, POST, PUT, DELETE');
       response.header('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Accept');proceed();});
    
    server.get('/info',(request, response)=>{
       response.json({country:'India', currencyCode:'INR'});});
    server.listen(3000,()=>{
       console.log('Application is live on port 3000');});

    Run the express API server: Now you have to start the server with the help of the below command.

    npm start
    

    Create a Vanilla JS Application: Now you have to create a vanilla JavaScript application for consuming the above API server endpoint. For this you have to run the following commands in the terminal to create a basic structure for creating our JS application.

    mkdir cors-test
    cd cors-test
    touch index.html 
    

    Now, change the project structure’s index.html file to request data from the express API server and show it in the user interface.

    The index.html file is as follows −

    <!DOCTYPE html><html lang="en"><body><h1>Data from Server</h1><div id="infoDisplay"></div><script>
             document.addEventListener('DOMContentLoaded', () => {
                const infoContainer = document.getElementById('infoDisplay');
                fetch('http://localhost:3000/info').then(serverResponse => serverResponse.json()).then(info => {
                   const {
                      country,
                      currencyCode
                   } = info;
                   infoContainer.innerHTML = `
                         
          	<p>Country: ${country}</p><p>Currency Code: ${currencyCode}</p>
                      `;
                }).catch(fetchError => {
                   console.warn('Failed to retrieve data:', fetchError);
                   infoContainer.innerHTML = ' < p > Error retrieving data.Please
                   try again later. < /p>';
                });
             });
          </script></body></html>

    Run the Vanilla JS Application: Now you can open the index.html file you have created above and see the output in the browser.

    Output

    This will generate the below result −

    CORS Example

    Common CORS Issues

    Here are some of the common issues are listed for your reference −

    Unauthorized Access Blocked by CORS

    One of the most common CORS issue is getting the error ‘Access to XMLHttpRequest at ‘URL’ from origin ‘Origin’ has been blocked by CORS policy’ in the browser console.

    To handle this problem you need to setup your server to provide the required CORS headers to enable access from the requesting origin.

    Example using Node.js and Express.js

    Following is the example using node.js and express.js −

    const express =require('express');const server =express();// Enable CORS for a specific origin
    server.use((request, response, proceed)=>{
       response.setHeader('Access-Control-Allow-Origin','https://example.com');
       response.setHeader('Access-Control-Allow-Methods','GET, POST, PUT, DELETE');
       response.setHeader('Access-Control-Allow-Headers','Content-Type, Authorization');// If cookies are needed
       response.setHeader('Access-Control-Allow-Credentials','true');proceed();});// Your API routes
    server.get('/api/info',(request, response)=>{// Your response logic
       response.json({ details:'Information from the server'});});
    
    server.listen(3000,()=>{
       console.log('Application active on port 3000');});

    In this example, we enabled CORS for a given origin (https://example.com) by giving the headers. This enables requests from https://example.com to access server resources.

    Missing CORS Headers

    Sometimes the server fails to include the required CORS headers when it responses, leading the browser to block the request.

    Make that your server contains the necessary CORS headers in its answers to allow cross-origin queries.

    Example using Node.js and Express.js

    Here is the example using node.js and express.js −

    const express =require('express');const server =express();// Add CORS headers to all responses
    server.use((request, response, proceed)=>{
       response.setHeader('Access-Control-Allow-Origin','*'); 
       response.setHeader('Access-Control-Allow-Methods','GET, POST, PUT, DELETE');
       response.setHeader('Access-Control-Allow-Headers','Content-Type, Authorization');// If cookies are needed
       response.setHeader('Access-Control-Allow-Credentials','true');proceed();});// Your API routes
    server.get('/api/info',(request, response)=>{// Your response logic
       response.json({ info:'Information from the server'});});
    
    server.listen(3000,()=>{
       console.log('Application is now active on port 3000');});

    In this example, CORS headers are added to all responses using middle-ware, enabling requests from any origin. But for security reasons, acceptable origins must be limited in a production environment.

  • JavaScript – Code Testing with Jest

    You can increase your application’s reliability and maintainability by testing your code to find errors earlier using Jest. Jest is a popular choice for JavaScript testing, particularly for applications made using Node.js, React, Angular, and Vue.js. Let us look at Jest’s features and how to use them.

    What is Jest?

    The Jest testing framework, created by Facebook, focuses efficiency and adaptability. Jest easily integrates with JavaScript and TypeScript applications and supports popular libraries and frameworks like React. Among its main features are integrated mocking support, zero configuration and snapshot testing.

    Features of Jest

    Here are some features you need to know before working with Jest −

    • Zero Config: To start creating and delivering tests, virtually no configuration is needed. But the test suite can also be provided using a configuration file.
    • Snapshots: Snapshot testing can also be enabled using Jest. In simple terms, the saved snapshot and the snapshots are compared to see whether there is any matching functionality.
    • Isolated testing: To reduce execution time, Jest tests are executed in parallel.
    • Mocking Support: Jest makes it easy to create fictitious functions so you can test how your code interacts with other components.

    Setting Up Jest

    For using Jest you have to first install it in your project. Use the below steps −

    1. Initialize a Project: So you have to open a terminal and navigate to your project folder then run the below command −

    npm init -y
    

    2. Install Jest: Then you have to run the below command −

    npm install --save-dev jest
    

    3. Add Jest to Your Scripts: Locate the package.json file and in this file you have to add the following line −

    "scripts":{"test":"jest"}

    Now you can write your first test for your JavaScript code.

    Example 1

    Here is the simple and basic test that checks if the function sum returns the proper result.

    // sum.jsfunctionsum(a, b){return a + b;}
    module.exports = sum;

    Test File

    Here is the test file code −

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

    Run the above test code by the following command −

    npm test
    

    In this test – expect(sum(1, 2)).toBe(3); checks that sum(1, 2) returns 3.

    Example 2

    Jest handles asynchronous testing easily. Let’s create an asynchronous function and test it.

    // fetchData.jsasyncfunctionfetchData(){return'freeCodeCamp';}
    module.exports = fetchData;

    Test File

    Here is the test file code −

    // fetchData.test.jsconst fetchData =require('./fetchData');test('the data is freeCodeCamp',async()=>{const data =awaitfetchData();expect(data).toBe('freeCodeCamp');});

    Here Jest executes expect after fetchData() is complete.

    Example 3

    Mock functions let you test and model code interactions without needing the actual function. This is how to create a simple mock function.

    const myMockFunction = jest.fn(x=> x +42);test('mock function test',()=>{expect(myMockFunction(0)).toBe(42);});

    In this test, jest.fn() is used to generate a mock function that adds 42 to any input value. This test confirms that when myMockFunction(0) is invoked, 42 is returned

  • JavaScript – Circular Reference Error

    When an object creates a direct or indirect reference to itself, it is known as circular referencing. It makes the loop closed. JavaScript has the same circular referencing issue as other programming languages. A few errors of JavaScript circular referencing modes will be discussed in this chapter.

    What is a Circular Reference in JS?

    In JavaScript, a circular reference happens when two or more objects make reference to one another in a way that starts a loop. You have a circular reference, for example- if object A refers to object B and object B in turn refers back to object A.

    Example

    Here is the basic example of circular reference in JavaScript −

    let person ={};let friend ={};// Making a circular reference
    person.bestFriend = friend;
    friend.bestFriend = person;

    This creates a loop in which person refers a friend, who in turn mentions the person.

    Problems With Circular References

    It is preferable to organize data without cross-references between objects in order to prevent circular references.

    • Memory leaks: These happen when JavaScript’s garbage collection refuses to remove objects with circular references resulting in memory that is not released.
    • Stringify errors in JSON: Errors happen when circular references are tried to be converted to JSON, for example, by using JSON.stringify(). Because this method cannot support circular structures, an error will be produced.
    let obj ={};
    obj.self = obj;// Throws "TypeError: Converting circular structure to JSON"JSON.stringify(obj);

    How to Fix Circular References

    A few standard methods can be used to correct circular references. These include using particular libraries that can handle circular structures, removing references prior to converting to JSON and rearranging data to prevent loops.

    Remove Circular References

    Find the location of the circular reference and remove it if it is not needed.

    let obj1 ={};// Avoid circular reference by not pointing obj1 back to obj2let obj2 ={ obj1: obj1 };
    
    console.log(JSON.stringify(obj2));

    Output

    This will generate the below result −

    {"obj1":{}}
    

    Use a Custom toJSON Method

    If you want to stringify an object with circular references you can create a custom toJSON function to ignore them.

    let obj ={};
    obj.self = obj;
    
    obj.toJSON=function(){let copy ={...this};// Remove circular referencedelete copy.self;return copy;};// This will now work without errors
    console.log(JSON.stringify(obj));

    Output

    This will lead to the below output −

    {}
    

    Use a Library

    Some libraries like flatted or circular-json can handle circular references automatically. Use the package instead of JSON.stringify() after installing it.

    // Using circular-json const CircularJSON =require('circular-json');let obj ={};
    obj.self = obj;let jsonString = CircularJSON.stringify(obj);// Converts circular structure to JSON without error
    console.log(jsonString);

    Output

    This will produce the following outcome −

    {"self":"~"}
  • JavaScript – Bubble Sort Algorithm

    The stages of Bubble Sort are covered in this chapter, which includes a JavaScript implementation. The word ‘sort’ refers to the process of rearranging the elements in ascending order.

    Bubble Sort Algorithm

    Bubble sort is a great starting point for those who are new to sorting. Since its algorithm looks similar how our brains usually think about sorting by comparison it is among the most simple sorting techniques.

    When using Bubble Sort the adjacent elements in the array are compared and if the first element is greater than the second the places are switched. In this way the highest value “bubbles” will come at the top.

    At the end of each iteration, the parts nearest the right are frequently in the correct order. The process is repeated until each element is in the right place.

    Now let us see what exactly bubble sort does −

    • Starting with the first element in the array and compare it to the current element.
    • If the array’s current element is bigger than the next element, switch them.
    • If the current element is less than it and just move on to the next one.
    • Continue from Step 1 again.

    Demonstration of Bubble Sort

    Here are the iterations of the bubble sort −

    Iteration 1:[8,3,7,1,5]->[3,8,7,1,5]->[3,7,8,1,5]->[3,7,1,8,5]->[3,7,1,5,8]
    Iteration 2:[3,7,1,5,8]->[3,7,1,5,8]->[3,1,7,5,8]->[3,1,5,7,8]
    Iteration 3:[3,1,5,7,8]->[1,3,5,7,8]->[1,3,5,7,8]
    Iteration 4:[1,3,5,7,8]->[1,3,5,7,8]
    Final Sorted List:[1,3,5,7,8]

    Implementing Bubble Sort in JavaScript

    The input of the bubbleSort function is the array arr. It uses two loops. The outer loop iterates over each element up to n-1 times, where n is the array’s length. The inner loop compares and switches adjacent elements if they are out of order.

    A swapped flag is used to optimize the sort. If the array is already sorted and no swaps are made during a pass so we can end the loop early.

    functionbubbleSort(arr){let n = arr.length;let swapped;for(let i =0; i < n -1; i++){
          swapped =false;for(let j =0; j < n -1- i; j++){// Compare adjacent elementsif(arr[j]> arr[j +1]){// Swap if they are in the wrong orderlet temp = arr[j];
                arr[j]= arr[j +1];
                arr[j +1]= temp;
                    
                swapped =true;}}// If no elements were swapped, the array is already sortedif(!swapped)break;}return arr;}// Example let arr =[8,3,7,1,5];
    console.log("Sorted array:",bubbleSort(arr));

    Output

    This will generate the below result after sorting the elements −

    Sorted array: [ 1, 3, 5, 7, 8 ]
    

    Another Way to Implement Bubble Sort

    Here is another way to create Bubble Sort in JavaScript using a slightly different structure −

    functionbubbleSort(arr){let n = arr.length;for(let i = n -1; i >0; i--){for(let j =0; j < i; j++){// Compare adjacent elementsif(arr[j]> arr[j +1]){// Swap if they are in the wrong order// Using destructuring for swapping[arr[j], arr[j +1]]=[arr[j +1], arr[j]];}}}return arr;}// Examplelet arr =[8,3,7,1,5];
    console.log("Sorted array:",bubbleSort(arr));

    Output

    This will produce the following result −

    Sorted array: [ 1, 3, 5, 7, 8 ]
    

    Complexities

    In the worst case scenario and average case time complexity the array is in reverse order so in this situation it has O(n2) time complexity.

    And in the optimal time complexity and in the ideal situation the array’s time complexity is O(n) and it is already sorted. The auxiliary space is O(1).

  • JavaScript – DOM DOMTokenList

    DOMTokenList

    The DOMTokenList is an interface in DOM (Document Object Model) which represents a set of space-separated tokens (classes). Generally, it is used for managing the classes in HTML elements.

    It may look like an array, but it is not. Similar to an array, you can loop through a DOMTokenList and access its tokens by index. However, you cannot use array methods such as push()pop(), or join() on a DOMTokenList.

    You can retrieve individual tokens using their numerical index in the DOMTokenList. For example, element.classList[0] would give you the first-class name of an element.

    The following diagram clearly explains the JavaScript DOMTokenList interface. As you can see a DOMTokenList can contain a list of values (tokens) −

    DOMTokenList

    The following interactive example will use 2-3 important methods as button functionalities. Whenever the user interacts with the page, the respective method will be performed −

    Click on the below buttons to see the changes…..

    TutorialspointAddRemoveToggle

    Below is the explanation of the example above:

    • If you click the “Add” button, the ‘DOMTokenList’ add() method will be called, and the class ‘tp’ will be added to “tutorials”.
    • If you click the “Remove” button, the remove() method will be called to remove the added class.
    • If you click the “Toggle” button, the toggle() method will be called, which will add and remove the class alternately.

    JavaScript DOMTokenList Methods

    The DOMTokenList is an interface that represents a set of space-separated tokens. These tokens can be seen in properties such as classList, HTMLLinkElement, relList, and many others.

    Following is a list of methods provided by the JavaScript DOMTokenList −

    Sr.NoMethod & Description
    1add()This method adds one or more tokens specified in the parameter to the DOMTokenList.
    2contains()This method checks whether the list contains the specified token, and returns a boolean value accordingly.
    3entries()This method returns an iterator that is allowing to go through all the key/value pairs.
    4forEach()This method calls the callback function mentioned in the parameter once for each value pair in the list in the order of their insertion.
    5item()This method returns a token from the DOMTokenList specified by the index in the parameter.
    6keys()This method returns an iterator which allows you to go through all the keys contained in the token list.
    7remove()This method removes one or more tokens specified in the parameter to the DOMTokenList.
    8replace()This method replaces the existing token in DomTokenList with a new token specified in the parameter.
    9supports()This method checks whether the token specified in the parameter is supported in DOMTokenList.
    10toggle()This method dynamically adds or removes a token or class from an element class attribute.
    11values()This method returns an iterator allowing us to go through all values contained in the token list.

    JavaScript DOMTokenList Properties

    Following is a list of properties provided by the JavaScript DOMTokenList −

    Sr.NoProperties & Description
    1lengthThis method returns the number of tokens in a token list.
    2valueThis method returns the DOMTokenList serialized as a string.

    Example 1: Retrieving the length of the DOMTokenList.

    The following example demonstrates the usage of the DOMTokenList length property −

    <!DOCTYPE html><html lang="en"><body><p>DOMTokenList Example</p><div id="myList"class="tp1 tp2 tp3">I'm inside div.</div><span id="result"></span><script>let list = document.getElementById("myList").classList;
            document.getElementById('result').innerHTML ="DOMTokenList length (number of classes) is : "+ list.length;</script></body></html>

    The above program returns the length of the DOMTokenList (or number of classes) −

  • JavaScript – DOM NodeList

    DOM NodeList

    The NodeLists are similar to an array or HTMLCollection containing the HTML elements. However, it is not the same as the array or HTML collection.

    All modern browsers return the node list when you use querySelectorAll() method and childNodes properties. You can traverse the NodeList as an array but can’t use other array methods like map()filter(), etc, with node lists.

    The following diagram clearly explains the JavaScript NodeList interface. As you can see, an HTML code snippet contains all types of nodes:

    DOM NodeList

    JavaScript DOM NodeList Methods

    Following is a list of methods provided by the JavaScript NodeList −

    Sr.NoMethod & Description
    1entries()This method retrieves an iterator, that allows us to iterate through all the key/value pairs in the object.
    2forEach()This method calls the callback function mentioned in the parameter once for each value pair in the list in the order of their insertion.
    3item()This method retrieves a node from the NodeList specified by the index in the parameter.
    4keys()This method retrieves an iterator that allows us to go through all the keys contained in the NodeList.

    JavaScript DOM NodeList Properties

    Following is a list of properties provided by the JavaScript NodeList −

    Sr.NoProperties & Description
    1lengthThis method returns the number of items in the NodeList.

    Example 1: Retrieving a specific element from a NodeList.

    The following example demonstrates the usage of the JavaScript DOM NodeList −

    <!DOCTYPE html><html lang="en"><head><title>JavaScript DOM NodeList</title></head><body><div><p>This is first paragraph.</p><p>This is second paragraph.</p><p>This is third paragraph.</p><p>This is fourth paragraph.</p></div><script>
            let myNodeList = document.querySelectorAll('p');
            //you can access the node list by index
            //access the third node list
            alert("This is third P: " + myNodeList[2].innerHTML);
        </script></body></html>

    The program uses “querySelectorAll()” to select all “p” elements as a NodeList. By passing the index value as “2”, it alerts the third “p” element in the document −

    Example 2: Adding Style to NodeList (<div>) element.

    In this example, we use the “getElementsByTagName(‘div’)” method to select all “<div>” elements and return them as a NodeList. Now, we can apply styles to these elements −

    <!DOCTYPE html><html lang="en"><head><title>JavaScript DOM NodeList</title><style>
            button{
                padding: 8px 20px;
                margin: 20px 0px;
                border-radius: 5px;
                cursor: pointer;
                font-size: 16px;
            }
        </style></head><body><p>Click the button below to add style to all "div" elements.</p><div>Div 1</div><div>Div 2</div><div>Div 3</div><div>Div 4</div><div>Div 5</div><button id="btn">Add style</button><script>
       document.getElementById('btn').addEventListener("click", ()=>{
          //using getElementsByTagName() method
          let myNodeList = document.getElementsByTagName('div');
          //using length property
          for(let i = 0; i<myNodeList.length; i++){
              myNodeList[i].style.color = 'white';
              myNodeList[i].style.padding = "10px";
              myNodeList[i].style.margin = "5px";
              myNodeList[i].style.border = "1px solid black";
              myNodeList[i].style.backgroundColor = "green";
          }
       });
        </script></body></html>

    On executing the above program, a button is displayed. When clicked, it applies a new style to all “div” elements −

    Example 3: Using the forEach() method to traverse the NodeList elements.

    In this example, we have four <p> elements. We use “querySelectorAll(‘.lang’)” to select all elements with the class “lang” and traverse the NodeList using “forEach()” method −

    <DOCTYPE html><html><body><p class="lang"> English </p><p class="lang"> German </p><p class="lang"> Arabic </p><p class="lang"> Hindi </p><br><div id ="output"></div><script>const output = document.getElementById('output');
          output.innerHTML +="All languages are: <br>";const langs = document.querySelectorAll('.lang');
          langs.forEach((language)=>{
             output.innerHTML += language.innerHTML +'<br>';})</script></body></html>

    After execution, the above program displays all “p” elements having the the class name equal to “lang” −

    Example 4: Retrieving the length of the NodeList.

    In the below code, we have used the ‘length’ property of the NodeList to count the number of nodes in the NodeList.

    <DOCTYPE html><html><body><div class="fruit"> Apple </div><div class="fruit"> Orange </div><div class="fruit"> Banana </div><div class="fruit"> Mango </div><div id ="output">Total number of fruits are :</div><script>const fruits = document.querySelectorAll('.fruit');
          document.getElementById('output').innerHTML += fruits.length;</script></body></html>

    The above program returns the length of NodeList −

    Difference between HTMLCollection and NodeList

    The HTMLCollection and NodeList look similar, but there is a minor difference between them, which we have explained in the table below −

    FeatureHTMLCollectionNodeList
    Return byGenerally, getElementByClassName(), getElementByTagName methods, and children properties return the HTML collection.Generally, the querySelectorAll() method and childNodes property return the Node list.
    Array methodsIt supports limited array methods.It also supports limited array methods like forEach().
    Live collectionSome browser supports live collection with HTML collection.It updates if you update the DOM element.