Category: Miscellaneous

  • Style Guide

    A JavaScript style guide is a set of general rules that regulate how to write JavaScript code. These rules can include − which quotes to use, how many spaces to indent, the maximum line length, using single-line comments, marked with //, etc.

    When any company starts developing a real-time JavaScript project, 100’s of developers work on that. If each developer follows a different style of writing code, it becomes very hard to manage complex code. So, it is important to follow the same code style throughout the project.

    Here, we have covered some essential coding conventions to follow while developing the project.

    Code Indentation

    You should always intend your code with fixed spaces (either 2, 3 or 4 spaces) according to the coding convention of your project. Also, the code should not contain trailing white spaces.

    Example

    In the code below, we have used the three spaces indentation in the function.

    <html><body><h2> Intendation Conventions </h2><div id ="output"></div><script>const output = document.getElementById('output');functionfunc(){
    
            output.innerHTML ="Function executed!";return10;}func();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Comments

    You should always use the line comments rather than the block comments, and line comments should start with the left part of the code.

    Example

    In the code below, we used the // line comments to comment the code.

    <html><body><h2> Comment Conventions </h2><div id="output"></div><script>const output = document.getElementById('output');
    
      output.innerHTML ="Hello World!";// var a = 10;// var b = 20;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Variable Declaration

    Always declare the variable at the top of its scope. If a variable is a global variable, declare it at the top of the file. Similarly, if the variable is in th block or function, declare it at the top of the block or function. Furthermore, variable names must start with the letter.

    Example

    In the code below, we have declared the variable at the top of the code, and the name of each variable starts with a letter.

    <html><body><h2> Variable Conventions </h2><div id="output"></div><script>var a =10;var b =20;
    
      document.getElementById('output').innerHTML ="The sum of 10 and 20 is: "+(a + b);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Identifier Names in camelCase

    In JavaScript, always use the camelCase convention to define the identifier. In the camelCase convention, the first letter of the identifier should be lowercase, and the first letter of the 2nd word should be in the uppercase. Here, identifiers include function names, variable names, object names, class names, etc.

    Example

    In the code below, 'greetMessage' and 'executeGreet' both identifiers are in the camelCase.

    <html><body><h2> camelCase Conventions </h2><div id="output"></div><script>var greetMessage ="Hello Developers!";let output = document.getElementById('output');// Function name with camelCasefunctionexecuteGreet(){
    
         output.innerHTML = greetMessage;}executeGreet();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Spaces, and Brackets

    In JavaScript, we should include white space before and after each operator like +, 'typeof, etc. Furthermore, it is also vital to include white space around brackets.

    Example

    In the code below, we added proper space after the 'if' condition. Also, we added white space before and after += operator.

    <html><body><h2> Space and all brackets Conventions </h2><div id="output"></div><script>let output = document.getElementById('output');if(9>10){
    
         output.innerHTML +="9 is greater than 10";}else{
         output.innerHTML +="9 is not greater than 10";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Object Rules

    In JavaScript, we use the = assignment operator and open bracket { after the object identifier. Next, we write the object properties (key-value pairs separated by semicolon), and we write each property in the new line and separate them with a comma (,). Also, we don't put a comma after the last object property. At the end, we add a semicolon (;) after adding a closing bracket.

    Example

    In the code below, we have defined the object according to the object guidelines. Also, we have shown objects on the web page using the JSON.stringify() method.

    <html><body><h2> Object Conventions </h2><div id="output"></div><script>const obj ={
    
         prop1:'value1',
         prop2:'value2',
         prop3:'value3'};
      document.getElementById("output").innerHTML =JSON.stringify(obj,null,2);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Statement Rules

    There are 3 types of statements in JavaScript.

    • Simple one-line statement
    • Compound statement
    • Multi-line statement

    The simple one-line statement should always end with a semicolon.

    For the compound statement, we put white space and an open bracket after a statement in the same line. Next, we start adding the statement body from the next line, and in the last line, we add a closing bracket. We don't put a semicolon after the closing bracket.

    If the statement is too long and can't be written in a single line, we can add a line break after the operator.

    Example

    In the code below, we have defined single one-line, compound, and multi-line statements.

    <html><body><h2> Statement Guidelines Conventions </h2><div id="output"></div><script>const output = document.getElementById('output');// single line statementconst arr =["one","two","Three"];// Compound statementfor(let i =0; i < arr.length; i++){
    
      output.innerHTML += arr[i]+"&lt;br&gt;";}// Multi-line statementif(10&gt;9&amp;&amp;10&gt;5&amp;&amp;10&gt;6){
      output.innerHTML +="10 is greater than 9 and 10 is greater than 5 &lt;br&gt;";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Line Length

    It is always hard to read long lines of code. So, we should put a maximum 80 characters in a single line.

    Example

    In the code below, we have added half a string in a new line as it contains more than 80 characters.

    <html><body><h2> Line length Conventions </h2><div id="output"></div><script>let str =`This is too long a sentence. 
    
            Let's put the limit of 80 characters.`
      document.getElementById('output').innerHTML = str;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    We have explained the common style conventions in this tutorial. However, you can have your own coding conventions and follow them throughout the project.

  • Performance

    JavaScript is very important in every website today. If JavaScript fails, our website wouldn’t work properly. It is important to focus on the performance on JavaScript as it has impacts on delivering a positive user experience, retaining engagement, and ensuring business success. An optimized JavaScript would ensure the pages load faster and responsive interactions contribute to users satisfaction and hence higher conversion rates as well as higher search engine rankings (as the SEO would be better).

    In a competitive digital landscape, optimized JavaScript code not only attracts and retains users but also enhances resource efficiency, reducing server costs and providing a competitive advantage. With the increasing prevalence of mobile devices and the emphasis on Progressive Web Apps, performance optimization is not only a user expectation but a strategic necessity for businesses aiming to stand out and thrive in the online space.

    Optimizing DOM Manipulation

    DOM manipulation is where each element is represented as a node in the tree and accessed or modified via their ids, class names etc. These DOM manipulation operations should be minimized as much as possible and would have a significant impact on the speed of our application. Let us consider the below example where we are dynamically creating a list of 1000 items.

    Example

    Naive Code

    <!DOCTYPE html><html><body><ul id="itemList"></ul><script>const itemList = document.getElementById('itemList');// Inefficient DOM manipulationfor(let i =0; i <1000; i++){
    
         itemList.innerHTML +=&amp;lt;li&amp;gt;Item ${i}&amp;lt;/li&amp;gt;;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Optimized Code

    <!DOCTYPE html><html><body><ul id="itemList"></ul><script>// Efficient DOM manipulation using document fragmentconst itemList = document.getElementById('itemList');const fragment = document.createDocumentFragment();for(let i =0; i <1000; i++){const listItem = document.createElement('li');
    
         listItem.textContent =Item ${i};
         fragment.appendChild(listItem);}
      itemList.appendChild(fragment);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Asynchronous Operations with Promises

    To prevent the main thread from blocking, we must prioritize asynchronous programming. Consider this example: data retrieval from an API using Promises; in such instances, a Promise proves indispensable for managing asynchronous data fetching. Preventing the UI from freezing during operation; enhancing the overall user experience: these are the benefits.

    Example

    <!DOCTYPE html><html><body><h2>Asynchronous Operations with Promises</h1><div id="dataContainer"></div><script>// Fetch data asynchronouslyfunctionfetchData(){returnnewPromise((resolve, reject)=>{// Simulating an API call with a delaysetTimeout(()=>{const data ={ message:'Hello, world!'};resolve(data);},1000);});}// Usage of the fetchData functionfetchData().then(data=>{
    
            document.getElementById('dataContainer').textContent = data.message;}).catch(error=&gt;{alert('Error fetching data:', error);});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Deferred JavaScript Loading

    JavaScript is normally loaded when the page is opened, however by delaying the loading of JavaScript we can optimize page load performance especially when dealing with non-essential scripts. When browsers come across the <script> tag, they normally block the rendering until the script has finished downloading and executing. However, by using the defer attribute in the script tag, we can instruct the browser to continue downloading the script in the background while it continues to parse & render the HTML. The script is then executed after the HTML is completely parsed.

    Example

    <!DOCTYPE html><html><body><p>Deferred JavaScript Loading</p><script defer src="https://code.jquery.com/jquery-3.6.4.min.js"></script><div id="loadingMessage">JavaScript is loading...</div><script>// Add an event listener to indicate when the JavaScript is fully loaded
    
      document.addEventListener('DOMContentLoaded',function(){
         document.getElementById('loadingMessage').textContent ='JavaScript has finished loading!';});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Another option to the above code is to use the async attribute. While similar to defer, async loads the script asynchronously, but it doesn't guarantee the order of execution. The script that finishes loading first will be executed first.

    Avoiding Global Variables

    Global variables are those which are visible throughout the code, or have a big scope. It is import to understand if our code actually requires the scope of variables to be global or can it be managed efficiently by code encapsulation. The below examples demonstrates the usage of encapsulation to avoid global variables hence leading to better performance of the script.

    Example

    <!DOCTYPE html><html><body><h2>Avoiding Global Variables</h2><div id="result"></div><script>var resultElement = document.getElementById('result');// Inefficient use of global variablesvar globalVar =10;functionaddNumbers(x, y){return globalVar + x + y;}
    
    
      resultElement.innerHTML +="Using global variable, the sum is "+addNumbers(51,7)+"&lt;br&gt;";// Improved encapsulation(function(){var localVar =10;functionaddNumbers(x, y){return localVar + x + y;}
         resultElement.innerHTML +="Using encapsulation, the sum is "+addNumbers(51,7);})();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    While we have discussed performance optimization in this tutorial from a JavaScript point of view, it is important to note that certain optimizations remain constant irrespective of the language. This includes scenarios like using switch case instead of length if else if, memory management, concurrency, etc.

    The performance optimization of JavaScript has impacts across industries & applications. In ecommerce, a high speed page load has proven to enhance user engagement and boost conversation rates, while in social media JavaScript has helped in providing seamless interactions. News and media related websites benefit as the content gets updated quickly and only learning platforms (edtech industry) requires JavaScript for interactive educational components.

    On the other hand, financial applications, collaboration tools, gaming websites, and healthcare apps all demand optimized JavaScript to ensure their interfaces are responsive and process data in a timely manner.

  • Debouncing

    While developing the applications, sometimes it is really important to limit the function calls to improve the web application performance. Debouncing is a programming technique that helps in limiting the function calls.

    Lets learn more about debouncing in JavaScript.

    What is Debouncing?

    Debouncing is a simpler way to delay the execution of a particular function until a certain amount of time has passed since the last execution of the function. It is important to use debouncing when we want to avoid unnecessary repeated function calls. In short, it works as a rate-limiter.

    For example, when you press the button to call the elevator, it registers the event. After that, when you press the call button multiple times in a short period of time, it ignores the button press as the elevator cant come faster by pressing buttons multiple times.

    How to implement debouncing in JavaScript?

    We can implement debouncing in JavaScript in different ways, but one way is using the setTimeOut() method. Whenever any event occurs, it should call a particular function that returns a new function, which executes the particular after a certain amount of delay.

    Lets understand it in more depth via the example below.

    Example

    In the code below, when the user clicks the button, it calls the debounce() function.

    The debounce() function takes the function that we need to execute as a first parameter and time delay as a second parameter.

    In the debounce() function, we define the timeout variable to store the id of the timer and return the function. Inside the inner function, we get the context and arguments of the function execution call. After that, we clear the previous time out and set a new timer using the setTimeOut() method.

    We use the apply() method to call the function after a particular amount of the delay.

    <html><body><h2> JavaScript - Debouncing </h2><div id ="output"></div><button id ="btn"> Debounce </button><script>var output = document.getElementById("output");var btn = document.getElementById("btn");// Add event listener to button
    
      btn.addEventListener("click",debounce(function(){
         output.innerHTML ="Hello "+newDate().toLocaleTimeString();},2000));// Debounce functionfunctiondebounce(func, wait){// Initialize timeout variablevar timeout;// Return a functionreturnfunction(){// Save the context and arguments of the functionvar context =this,
            args = arguments;// Clear the timeoutclearTimeout(timeout);// Set the timeout
            timeout =setTimeout(function(){// Call the functionfunc.apply(context, args);}, wait);};}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    In the above output, try to click the button multiple times within a period of 2 seconds. It will execute the function only once.

    Benefits of Debouncing

    There are a lot of benefits of debouncing. Here, we have covered some of them.

    • Debouncing improves the performance of the web application by rate limiting.
    • It reduces the server load by making a limited number of requests in a certain period.
    • It enhances the user experience by improving the performance of the web application.
    • It prevents the unnecessary API calls, which reduces the cost.

    Real-world Use cases of Debouncing

    Here, we have covered some real-world use cases of debouncing.

    • Debouncing can be used with the search box. It makes the request to the server only when a user pauses the typing and reduces the API requests.
    • It can be used with infinite scroll and lazy loading. Developers can know when users stopped scrolling, fetch only the required data, and load them.
    • Debouncing can also be used with gaming controls to filter out accidental double or triple clicks.
  • Canvas

    Handling Canvas with JavaScript

    The HTML <canvas> element can be used to create and draw graphics on the web page. It can draw various graphics or shapes, like lines, circles, etc., on the web page and animate them.

    You can define <canvas> element in HTML, and after that, you need to use JavaScript to draw graphics on the web page. Let’s look at the syntaxes to define a canvas element in HTML and manipulate with JavaScript.

    Syntax

    Use the following syntax to create an HTML canvas element.

    <canvas id="myCanvas" width="480" height="320">
       Your browser does not support the HTML canvas tag.</canvas>

    In the above syntax, we have defined the HTML <canvas> element with id as ‘myCanvas’. The message written in between <canvas> tags will be displayed when the browser doesn’t support the <canvas> element.

    We access the canvas element using the getElementById() method of document object. Look at below syntax −

    var canvas = document.getElementById('canvas_id');var ctx = canvas.getContext('2d');

    In JavaScript, we can use the getContext(‘2d’) method to get the context of the 2D canvas. Next, we can use various methods to draw a shape and fill in the color by taking the ‘ctx’ variable as a reference.

    Examples

    Example: Drawing a rectangle

    In the code below, we have added the <canvas> element in HTML.

    In JavaScript, we have used the getContext(‘2d’) method to access the context of the canvas. After that, we used the fillstyle() method to color the element in the canvas. The fillRect() method is used to draw a rectangle. It takes the coordinates of 4 corners in the canvas.

    <html><body><h2> JavaScript - Canvas </h2><p> Drawing Rectangle on Canvas using JavaScript</p><canvas id ="myCanvas" width ="600" height ="300" style ="border:1px solid #000000;">
    
      Your browser does not support the HTML canvas tag.&lt;/canvas&gt;&lt;script&gt;var canvas = document.getElementById("myCanvas");// Getting the 2D context of the canvasvar ctx = canvas.getContext("2d");// Drawing rectangle using canvas
      ctx.fillStyle ="#FF0000";
      ctx.fillRect(50,30,470,240);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example: Drawing a circle

    In the code below, we used the arc() method to draw a circle. It takes the coordinates for the circle position as the first 2 parameters and the radius of the circle as a third parameter.

    <html><body><h2> JavaScript - Canvas </h2><p> Drawing circle on Canvas using JavaScript</p><canvas id ="myCanvas" width ="600" height ="300" style ="border:1px solid #000000;">
    
       Your browser does not support the HTML canvas tag.&lt;/canvas&gt;&lt;script&gt;var c = document.getElementById("myCanvas");// Getting the 2D context of the canvasvar ctx = c.getContext("2d");// Drawing circle using canvas
      ctx.beginPath();
      ctx.arc(300,150,100,0,2* Math.PI);
      ctx.stroke();
      ctx.fillStyle ="green";
      ctx.fill();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example: Drawing a lines

    In the code below, we have drawn the lines using the moveTo() and lineTo() methods. The moveTo() method takes the starting point of the line as a parameter, and the lineTo() method takes the ending point of the line as a parameter.

    <html><body><h2> JavaScript - Canvas </h2><p> Drawing lines on Canvas using JavaScript</p><canvas id ="myCanvas" width ="600" height ="300" style ="border:1px solid #000000;">
    
      Your browser does not support the HTML canvas tag.&lt;/canvas&gt;&lt;script&gt;var canvas = document.getElementById("myCanvas");// Getting the 2D context of the canvasvar ctx = canvas.getContext("2d");// Drawing lines using canvas
      ctx.moveTo(0,0);
      ctx.lineTo(300,200);
      ctx.stroke();
      ctx.moveTo(300,200);
      ctx.lineTo(400,0);
      ctx.stroke();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example: Drawing a Linear gradient

    <html><body><h2> JavaScript - Canvas </h2><p> Drawing linear gradient on Canvas using JavaScript</p><canvas id ="myCanvas" width ="600" height ="300" style ="border:1px solid #000000;">
    
      Your browser does not support the HTML canvas tag.&lt;/canvas&gt;&lt;script&gt;var canvas = document.getElementById("myCanvas");// Getting the 2D context of the canvasvar ctx = canvas.getContext("2d");// Drawing a linear gradient
      ctx.beginPath();var grd = ctx.createLinearGradient(0,0,440,0);
      grd.addColorStop(0,"yellow");
      grd.addColorStop(1,"white");
      ctx.fillStyle = grd;
      ctx.fillRect(10,10,550,240);
      ctx.fill();
      ctx.closePath();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example: Text Rendering

    In the below example, we have rendered a text message "Hello" on the canvas. For this, we have used fillText() method. The fillText() method in HTML Canvas draws a text string on a canvas element.

    <html><body><h2> JavaScript - Canvas </h2><p> Rendering text on Canvas using JavaScript</p><canvas id ="myCanvas" width ="600" height ="200" style ="border:1px solid #000000;">
    
      Your browser does not support the HTML canvas tag.&lt;/canvas&gt;&lt;script&gt;const canvas = document.getElementById('myCanvas');// Getting the 2D context of the canvasconst ctx = canvas.getContext('2d');
    ctx.font ='30px Arial';
    ctx.fillStyle ='red';
    ctx.fillText('Hello, Canvas!',150,100);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    We have learned to use <canvas> elements in HTML and draw graphics by accessing elements using JavaScript. We can draw various shapes and add colors to shapes.

  • Graphics

    In JavaScript, graphics can be created using the Canvas API. However, developers can also use some other libraries, like p5.js, chart.js, pllotly.js, Google charts, etc., to draw various graphics and charts.

    Here, we will explore some of these libraries and learn about them with help of some examples

    WebGL

    WebGL allows developers to create graphics from scratch using the code, and integrate it in the web pages. It operates directly with the HTML <canvas> element, allowing for GPU-accelerated usage of physics and image processing and effects as part of the web page canvas.

    WebGL allows to development of a wide range of applications from 2D games to complex 3D visualization applications. Also, it is supported by most modern browsers, which makes it a go-to choice for developers to develop graphics.

    Example

    In the code below, we have used the <canvas> element to create a canvas and accessed it in the JavaScript using the id. Next, we used the getCContext() method to get the context of the WebGL. If it is not supported by the browser, the getContext() method returns undefined value.

    In the initiateShader() function, we compile the shader source code into shaders, attach those shaders to a program, and then link the program so it can be used in a WebGL context. The loadShader() function loads and compiles the shader code.

    In the drawScene() function, we use the useProgram() method by passing the graphics info as a parameter to draw a triangle on the canvas. In the output, you can observe the red triangle on the black canvas.

    <html><body><h2> JavaScript -Graphics(WebGL)</h2><canvas id="webgl-canvas" width="600" height="400"></canvas><div id="error"></div><script>// Get the canvas element and its WebGL contextvar canvas = document.getElementById('webgl-canvas');let errorDiv = document.getElementById('error');// Get context of webglvar gl = canvas.getContext('webgl');if(!gl){
    
         console.error('Your browser may not support WebGL.');}// Vertex shader programvar vsSource =`
         attribute vec4 aVertexPosition;
         void main(void) {
            gl_Position = aVertexPosition;
         }
         ;// Fragment shader programvar fsSource =
      void main(void) {
         gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red color
      }
      `;functioninitShaderProgram(gl, vsSource, fsSource){const vertexShader =loadShader(gl, gl.VERTEX_SHADER, vsSource);const fragmentShader =loadShader(gl, gl.FRAGMENT_SHADER, fsSource);// Create the shader programconst shaderProgram = gl.createProgram();
         gl.attachShader(shaderProgram, vertexShader);
         gl.attachShader(shaderProgram, fragmentShader);
         gl.linkProgram(shaderProgram);// If creating the shader program failed, alertif(!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)){alert('Unable to initialize the shader program: '+ gl.getProgramInfoLog(shaderProgram));returnnull;}return shaderProgram;}functionloadShader(gl, type, source){const shader = gl.createShader(type);// Send the source to the shader object
         gl.shaderSource(shader, source);// Compile the shader program
         gl.compileShader(shader);// See if it compiled successfullyif(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)){
            error.innerHTML ='An error occurred compiling the shaders: '+ gl.getShaderInfoLog(shader);
            gl.deleteShader(shader);returnnull;}return shader;}// Initialize a shader program; this is where all the lighting// for the vertices and subsequently the creation of the// geometry and colors will be established.var shaderProgram =initShaderProgram(gl, vsSource, fsSource);// Collect all the info needed to use the shader program.// Look up which attribute our shader program is using// for aVertexPosition and look up uniform locations.var programInfo ={
         program: shaderProgram,
         attribLocations:{
            vertexPosition: gl.getAttribLocation(shaderProgram,'aVertexPosition'),},};// Vertices of the trianglevar positions =[0.0,1.0,// Vertex 1 (X, Y)-1.0,-1.0,// Vertex 2 (X, Y)1.0,-1.0,// Vertex 3 (X, Y)];var positionBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(positions), gl.STATIC_DRAW);// Draw the scenefunctiondrawScene(gl, programInfo, buffers){
         gl.clearColor(0.0,0.0,0.0,1.0);// Clear to black, fully opaque
         gl.clear(gl.COLOR_BUFFER_BIT);
         gl.useProgram(programInfo.program);// Tell WebGL how to pull out the positions from the position// buffer into the vertexPosition attribute.{const numComponents =2;// pull out 2 values per iterationconst type = gl.FLOAT;// the data in the buffer is 32bit floatsconst normalize =false;// don't normalizeconst stride =0;// how many bytes to get from one set to the nextconst offset =0;// how many bytes inside the buffer to start from
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.vertexAttribPointer(
               programInfo.attribLocations.vertexPosition,
               numComponents,
               type,
               normalize,
               stride,
               offset);
            gl.enableVertexAttribArray(
               programInfo.attribLocations.vertexPosition);}// Draw the triangle.
         gl.drawArrays(gl.TRIANGLES,0,3);}drawScene(gl, programInfo, positionBuffer);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    P5.js

    P5.js is also a very popular graphics library used to create various shapes by writing the code. It also allows us to animate the shapes and make them visually more appealing. However, it is not limited to shape but it also allows to interact with audio, video, etc.

    Lets understand the usage of P5.js with the example below.

    Example

    In the code below, the program starts with two main functions: setup() and draw(). The setup() function is run once when the program starts, and it's used for initial setup tasks. The draw() function continuously executes the lines of code contained inside its block until the program is stopped or noLoop() is called, making it ideal for animations.

    In the setup() function, we create a canvas and draw the circle on that. In the draw() function, we continuously change the position of the circles by redrawing them. The output of the below code shows the moving circle.

    <html><head><title>p5.js Example</title><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script></head><body><script>// Define variables for the circle's propertieslet x, y;// Positionlet dx =2;// Speed and direction on x-axislet dy =-2;// Speed and direction on y-axislet radius =50;// Circle's radiusfunctionsetup(){// Create a canvas that fills the windowcreateCanvas(windowWidth, windowHeight);// Initialize circle's position to center of the canvas
    
         x = width /2;
         y = height /2;}functiondraw(){background(220);// Fill the background with a light gray color// Draw a circle with a random fill colorfill(random(255),random(255),random(255));ellipse(x, y, radius *2);// Circle diameter is twice the radius// Update the position of the circle
         x += dx;
         y += dy;// Check for bouncingif(x + radius &gt; width || x - radius &lt;0){
            dx =-dx;// Reverse direction on the x-axis}if(y + radius &gt; height || y - radius &lt;0){
            dy =-dy;// Reverse direction on the y-axis}}// Resize the canvas when the window is resizedfunctionwindowResized(){resizeCanvas(windowWidth, windowHeight);}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Plotly.js

    Plotly.js is a JavaScript library that allows developers to create various types of high-quality graphs and visualizations with ease. We can use it to draw statistical charts, 3d charts, etc. The Plotly.js library can be integrated into various programming languages and frameworks.

    Example

    In the code below, we have created the trace1 object, which contains the x, y, and type properties. After that, we used the newPlot() method to create a line chart using the given data points.

    <html><body><h2> JavaScript - Graphics </h2><div id ="plotlyChart" style="width:600px;height:400px;"></div><script src="https://cdn.plot.ly/plotly-latest.min.js"></script><script>// Create a simple line chartvar trace1 ={
    
         x:[1,2,3,4],
         y:[10,15,13,17],
         type:'scatter'};var data =[trace1];
      Plotly.newPlot('plotlyChart', data);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Chart.js

    Chart.js is also a JavaScript library that allows developers to draw various kinds of charts. It supports six chart types: line, bar, radar, doughnut, pie, and polar area.

    Example

    In the code below, we used the Chart() constructor from the chart.js library to create a new bar chart.

    <html><body><h2> JavaScript - Graphics </h2><canvas id="chartjsBarChart" width="600" height="400"></canvas><script src="https://cdn.jsdelivr.net/npm/chart.js"></script><script>// Get Canvas contextvar ctx = document.getElementById('chartjsBarChart').getContext('2d');// Create a chartvar myChart =newChart(ctx,{
    
         type:'bar',
         data:{
            labels:['Red','Blue','Yellow','Green','Purple'],
            datasets:[{
               label:'# of Votes',
               data:[1,6,3,5,2],
               backgroundColor:['rgba(255, 99, 132, 0.2)','rgba(54, 162, 235, 0.2)','rgba(255, 206, 86, 0.2)','rgba(75, 192, 192, 0.2)','rgba(153, 102, 255, 0.2)'],
               borderColor:['rgba(255, 99, 132, 1)','rgba(54, 162, 235, 1)','rgba(255, 206, 86, 1)','rgba(75, 192, 192, 1)','rgba(153, 102, 255, 1)'],
               borderWidth:1}]},
         options:{
            scales:{
               y:{
                  beginAtZero:true}}}});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Google Charts

    Google Charts library also provides various types of charts, including the ones below.

    • Scatter Chart
    • Bar / Column Chart
    • Org Chart
    • Area Chart
    • Donut Chart
    • Map / Geo Chart
    • Line Chart
    • Pie Chart

    However, there are some more JavaScript libraries like D3.js available on the internet that can be used to draw various kinds of graphics.

  • Currying

    In JavaScript, currying is a functional programming technique that is used to transform a function that takes multiple arguments into a sequence of functions that each takes a single argument. Currying is mainly used in event handling and to avoid passing the same variable as a function argument multiple times.

    How to achieve currying in JavaScript?

    There are two different ways to achieve currying in JavaScript, as given below.

    • Using the closures function
    • Using the bind() method

    Currying using closures

    In JavaScript, closures is a technique in which inner functions can access the variables of the outer functions. To achieve currying using the closures technique, we can use the sequence of functions, each taking a single argument.

    Syntax

    Users can follow the syntax below to achieve currying using the closures.

    functionfuncName(a){returnfunction(b){// add more functions// ORreturn a * b;}}funcName(a)(b);

    In the above syntax, ‘funcName()’ function takes a single parameter, and it contains the inner function. The inner function also takes 1 parameter, and we use parameters of the outer and inner functions in the body of the inner function.

    The above function given in the syntax is similar to the below function.

    functionfuncName(a, b){return a * b;}funcName(a, b);

    Let’s understand currying via examples.

    Example

    In the code below, we have created the mul() function, which takes the single value as a parameter and returns the function taking ‘b’ as a parameter. The inner function also returns another function, which takes the ‘c’ as a parameter and returns the multiplication of the ‘a, ‘b, and ‘c.

    When we call mul(2) function, it returns the whole inner function as shown below.

    returnfunction(b){returnfunction(c){return a * b * c;}}

    When we call the mul(2)(3) function,

    returnfunction(c){return a * b * c;}

    When we call mul(2)(3)(4), it returns the result from the second inner function.

    In the output, you can observe that the function returns the result 24, which is the multiplication of 3 values.

    <html><head><title>JavaScript currying using using closures</title></head><body><div id ="output"></div><script>// Achieving the currying functionmul(a){returnfunction(b){returnfunction(c){return a * b * c;}}}// Calling the currying functionlet result =mul(2)(3)(4);
    
      document.getElementById("output").innerHTML ="The result is: "+ result;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The result is: 24
    

    This way, currying helps to make code more modular and reusable as it uses higher-order functions. Whenever it is a must to pass a number of arguments equal to the parameters of the function to get accurate results, currying is useful. For example, if you don't pass 3 arguments in the above example, it won't return the result.

    Currying using bind() method

    In JavaScript, the bind() method is used to create a new function and store it in the variable. The bind() is often used to partially prepend arguments to the current arguments of the function, effectively allowing you to curry functions.

    Syntax

    Users can follow the syntax below to use the bind() method to achieve currying in JavaScript.

    let multiplyByTwo =multiply.bind(null,2);let multiplyByTwoAndThree =multiplyByTwo.bind(null,3);multiplyByTwoAndThree(4);// Outputs: 24

    In the above syntax, 'multiply' can be a function taking multiple arguments. We prepend arguments one by one using the bind() method and achieve currying.

    Example

    In the code below, the multiply() function takes 3 arguments and returns the multiplication result. The 'multiply.bind()', adds one argument to the multiply() function, and returns the updated function. Similarly, the 'multiplyByTwoAndThree()' function stores the multiply function having two predefined arguments bound to it.

    When we call the 'multiplyByTwoAndThree()' function with the single argument, it returns the 60, multiplication of all 3 arguments.

    <html><head><title>JavaScript currying using bind() method</title></head><body><div id ="output"></div><script>// Original multiply function that accepts three argumentsfunctionmultiply(x, y, z){return x * y * z;}// Using the bind() method to achieve currying by partially applying the first argument (2)let multiplyByTwo =multiply.bind(null,2);// Further currying by partially applying the second argument (3).let multiplyByTwoAndThree =multiplyByTwo.bind(null,3);// Finally calling the curried function with the third argument (10) and outputting the result
    
      document.getElementById("output").innerHTML ="The result is: "+multiplyByTwoAndThree(10);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The result is: 60
    

    Use cases of Currying

    The currying technique is used in a lot of scenarios in real-time software development as it allows code to be more modularized and reusable. Here, we have given some real-time use cases of currying.

    • Currying can be used to handle asynchronous operations, in which functions return the promises.
    • It is even helpful in handling situations where we need to partially apply functions with specific arguments that can represent the current context of the event.
    • It allows the creation of highly configurable middleware functions that can be used across different parts of the code.
  • Clickjacking Attack

    Clickjacking Attack

    An attacker employs clickjacking, a form of cyber-attack, to deceive a user into clicking on an object different from their perception; this deception may result in unintended actions. The attacker achieves this by overlaying invisible elements or frames over valid content thus camouflaging the malicious intent or manipulating the appearance of webpage elements outright.

    Severe risks such as unauthorized financial transactions, potential data breaches and compromise of sensitive information are posed by clickjacking. Clickjacking impacts users and website owners alike leading to legal consequences, financial loss, and heightened cybersecurity concerns. The deceptive nature of clickjacking can erode user trust with far-reaching consequences in the digital ecosystem.

    Disclaimer: The contents of this chapter are only for education purposes!

    How clickjacking works?

    Overlaying Content

    • The attackers create a malicious/spam/scam website or injects malicious code into a website which is actually legitimate in nature.
    • The attacker positions invisible elements or frames over the legitimate content on the page. These elements can be transparent iframes or other HTML elements.

    Deceptive Presentation

    • The attacker then entices the user to interact with the visible elements on the page, which are typically buttons, links, or forms.
    • However, these visible elements are actually on top of the invisible, malicious elements.

    User Interaction

    • When the user interacts with the visible elements (clicking, typing, etc.), they are unknowingly interacting with the hidden, malicious elements that are overlaid on top of the legitimate content.

    Unintended Actions

    • The attacker can manipulate the hidden elements to perform unintended actions on behalf of the user. This could include making unwanted transactions, changing account settings, or even submitting sensitive information.

    User Unawareness

    • Because the user believes they are interacting with the visible elements they see, they remain unaware that their actions are being redirected to perform malicious activities.

    Examples

    Example 1: Button Overlay

    The provided HTML code demonstrates a button overlay clickjacking example. The button is presented to the user, but it is actually overlaid on a hidden, malicious iframe, leading the user to a potentially harmful page.

    home.html

    <!DOCTYPE html><html><body><h2>This is content of the home page</h2><iframe src="legitimate-site.html" width="100%" height="100%"></iframe><div><button onclick="window.location.href='malicious-site.html'">Click Me</button></div></body></html>

    legitimate-site.html

    <!DOCTYPE html><html><body><header><h1>Welcome to Legitimate Site</h1></header><section><p>This is a legitimate website. You can trust the content here.</p></section><footer><p>© 2024 Legitimate Site. All rights reserved.</p></footer></body></html>

    malicious-site.html

    <!DOCTYPE html><html><head><style>
    
      body {
         font-family: Arial, sans-serif;}.danger-sign {
         color: red;
         font-size:2em;}.warning-message {
         color: red;
         font-weight: bold;}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;header&gt;&lt;h1 class="danger-sign"&gt; Danger: Malicious Site&lt;/h1&gt;&lt;/header&gt;&lt;section&gt;&lt;p class="warning-message"&gt;This website has been identified as potentially harmful. Visiting it may pose a security risk to your computer and personal information.&lt;/p&gt;&lt;/section&gt;&lt;footer&gt;&lt;p&gt;Please close this page immediately and do not proceed.&lt;/p&gt;&lt;/footer&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Clickjacking Attack

    Example 2

    When the webpage loads in this example, it initiates an automatic click on a button identified as "clickMe." This specific button, upon receiving user interaction by means of clicking, activates a JavaScript event that re-routes the user to a potentially harmful site named 'malicious-site.html.' Such covert manipulation disconcertingly guides users towards unintended destinations without their knowledge or consent. Always note: these practices are indeed, potentially harmful and unethical in nature; one must approach them with responsibility and within legal and ethical boundaries.

    The malicious-site.html code is same as above.

    home.html

    <!DOCTYPE html><html><head><style>
    
      body {
         display: flex;
         align-items: center;
         justify-content: center;
         height:100vh;
         margin:0;}
      button {
         position: absolute;
         z-index:1;
         background-color: transparent;
         border: none;
         font-size:20px;
         cursor: pointer;}&lt;/style&gt;&lt;/head&gt;&lt;body onload="myFunction()"&gt;&lt;h2&gt;Your Content Goes Here&lt;/h2&gt;&lt;button id="clickMe"&gt;Click Me&lt;/button&gt;&lt;script&gt;
      window.onload=function(){var button = document.getElementById("clickMe");
         button.click();};
      document.getElementById("clickMe").addEventListener("click",function(){
         window.location.href ="malicious-site.html";});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Clickjacking Attack

    Real World Clickjacking Incidents

    1. Facebook "Like" Button (2011)

    Attackers overlaid a malicious "Like" button on an enticing video thumbnail, tricking users into unknowingly liking a malicious page.

    2. Adobe Flash Update Scam (2015):

    Malicious buttons disguised as Adobe Flash updates were overlayed on legitimate websites, leading users to unwittingly download malware.

    3. Twitter Clickjacking Attack

    Malicious links on Twitter, disguised as enticing content, led users to unintentionally retweet and spread malicious content.

    4. LinkedIn Fake Connection Requests

    Clickjacking was used to trick LinkedIn users into connecting with fake profiles by overlaying connection request buttons on seemingly innocent content.

    5. Google Play Store Deception

    Malicious overlays on the Google Play Store tricked users into unintended downloads or actions, often related to ads.

    Preventive Measures

    1. X-Frame-Options Header

    Set the X-Frame-Options header to DENY or SAMEORIGIN in your web server's response to prevent your site from being embedded in iframes.

    2. Frame-Busting Scripts

    Implement frame-busting scripts in your web pages to prevent them from being embedded in iframes.

    3. Content Security Policy (CSP)

    Use Content Security Policy headers to control the sources from which your website can load content, reducing the risk of clickjacking.

    4. User Education

    Educate users about potential risks associated with interacting with unfamiliar or suspicious-looking content.

    As cybersecurity evolves, future trends in clickjacking may include more sophisticated techniques leveraging artificial intelligence, increased use of social engineering tactics, and a focus on bypassing advanced security measures. Additionally, with the rise of emerging technologies like augmented reality (AR) and virtual reality (VR), new vectors for immersive clickjacking experiences may emerge, demanding continuous innovation in defensive strategies and user awareness.

  • IndexedDB

    What is IndexedDB?

    IndexedDB, or Indexed Database, represents a low-level JavaScript API. Its function involves the storage and retrieval of voluminous structured data – this includes files and blobs. With its capabilities to work with client-side databases: it enables web applications to locally store, query, and modify data on the user’s device. This functionality proves particularly advantageous when constructing web applications that confront significant data volumes; operate without an internet connection, working offline and deliver responsive user experiences through local data caching.

    Key concepts and features of IndexedDB:

    • Asynchronous API − Relying on event-driven programming, IndexedDB utilizes an asynchronous API to prevent main-thread blocking and enhance user experience.
    • Database − IndexedDB databases, functioning as containers for object stores, facilitate the organization, retrieval and deletion of data.
    • Object Store − An object store akin to a table in a relational database, encapsulates collections of JavaScript objects; it provides support for CRUD operations.
    • Index − Indexes in object stores can enhance the efficiency of data querying, as they are able to improve search and sort performance based on specific fields.
    • Transactions − Transactions in IndexedDB perform all operations, guaranteeing consistency and integrity through their ability to make multiple actions either succeed or fail as a unit.

    Why use IndexedDB?

    Web developers, in their search for efficient client-side storage solutions, find IndexedDB indispensable. Its asynchronous nature guarantees a responsive user experience: it thwarts main-thread blocking; moreover, its support for transactions by maintaining data integrity is commendable. IndexedDB is capable of managing significant volumes of structured data locally; this capability significantly enhances offline functionality a reduction on the need for relentless server communication. With its flexible key structure, indexing support for optimized queries, and the ability to upgrade schema; it stands as a robust choice for constructing web applications. These applications often require local storage, offline support and most importantly effective data management.

    CRUD Operations

    Let us now see the CRUD operation codes with IndexedDB.

    Create/Insert Operation

    To insert a new record into an object store, you utilize the add() method in IndexedDB. This method accepts a JavaScript object or value as its parameter and subsequently incorporates it within the designated object store. However, if there already exists an entry with identical key parameters; this operation will fail, thus rendering it ideal for guaranteeing uniqueness.

    const request = objectStore.add(data);
    request.onsuccess=()=>{// Handle success event};
    
    request.onerror=()=>{// Handle error};

    Read (Retrieve) Opeation

    The get() Method

    Utilize the get() method: it retrieves a singular record from an object store, this action is contingent upon your possession of knowledge regarding the specific key for your intended entry.

    The openCursor() Method

    Initiating an active cursor that iterates through records within an object store, the openCursor() method enhances efficiency and control by allowing for processing each individual entry; this proves useful in traversing all entries present in the said object store.

    const request = objectStore.openCursor();
    request.onsuccess=(event)=>{const cursor = event.target.result;if(cursor){const data = cursor.value;// Process data
    
      cursor.continue();}};
    request.onerror=()=>{// Handle error};

    Update Operation

    The put() method updates an existing record or adds a new one when the key doesn’t exist. Its versatility renders it suitable for data manipulation, specifically updating and inserting.

    const request = objectStore.put(data);

    Delete Operation

    To remove a specific record from an object store based on its key, one must employ the delete() method; this method offers a direct approach for deleting entries.

    const request = objectStore.delete(key);

    Implementation Example

    All the important methods of the above CRUD operation are implemented in this code. It presents database data as a table, each record accompanied by delete and update buttons. When you click on the create button, it displays an element for form creation on screen; thereby allowing entry of name and email to be inserted into the database. By default, this form remains hidden; it only appears upon button click and subsequently vanishes when its task is complete. The ‘prompt()’ method populates the details update form, a feature that provides convenience for users as alerts also appear in this same location. Moreover: pertinent alerts serve to signal either successful events or errors to the user.

    <!DOCTYPE html><html><head><style>
    
      body {
         font-family: Arial, sans-serif;
         margin:20px;}
      h2 {
         color: #333;}
      button {
         padding:8px;
         margin:5px;}
      #createForm, #updateForm {
         display: none;
         border:1px solid #ddd;
         padding:10px;
         margin-bottom:10px;}
      table {
         border-collapse: collapse;
         width:100%;
         margin-top:20px;
         width: auto;}
      th, td {
         border:1px solid #dddddd;
         text-align: left;
         padding:8px;}
      th {
         background-color: #f2f2f2;}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;h2&gt;IndexedDB CRUD Operations&lt;/h2&gt;&lt;button onclick="showCreateForm()"&gt;Create Data&lt;/button&gt;&lt;div id="createForm" style="display: none;"&gt;// hidden by default, displayed on create button click&lt;h3&gt;Create Data&lt;/h3&gt;&lt;label for="name"&gt;Name:&lt;/label&gt;&lt;input type="text" id="name" required&gt;&lt;br&gt;&lt;br&gt;&lt;label for="email"&gt;Email:&lt;/label&gt;&lt;input type="email" id="email" required&gt;&lt;br&gt;&lt;button onclick="createData()"&gt;Save&lt;/button&gt;&lt;button onclick="cancelCreate()"&gt;Cancel&lt;/button&gt;&lt;/div&gt;&lt;table id="data-table"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;ID&lt;/th&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Email&lt;/th&gt;&lt;th&gt;Actions&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;script&gt;const dbName ="myDatabase";let db;// Open/create indexedDB named myDatabase with version 11const request = window.indexedDB.open(dbName,11);
      request.onerror=(event)=&gt;{alert("Database error: "+ event.target.errorCode);};
      request.onsuccess=(event)=&gt;{
         db = event.target.result;showData();};
      request.onupgradeneeded=(event)=&gt;{
         db = event.target.result;const objectStore = db.createObjectStore("myObjectStore",{ keyPath:"id", autoIncrement:true});
         objectStore.createIndex("name","name",{ unique:false});
         objectStore.createIndex("email","email",{ unique:true});};functionshowData(){//populates the table from the dbconst transaction = db.transaction(["myObjectStore"],"readonly");const objectStore = transaction.objectStore("myObjectStore");const tableBody = document.querySelector("#data-table tbody");
         tableBody.innerHTML ="";const request = objectStore.openCursor();
         request.onsuccess=(event)=&gt;{const cursor = event.target.result;if(cursor){const row = tableBody.insertRow();
               row.insertCell(0).textContent = cursor.value.id;
               row.insertCell(1).textContent = cursor.value.name;
               row.insertCell(2).textContent = cursor.value.email;const actionsCell = row.insertCell(3);//update &amp; delete is performed on the basis of id, hence id is passed as parameter to functions when corresponding button is clicked
               actionsCell.innerHTML =`
               &lt;button onclick="showUpdateForm(${cursor.value.id})"&gt;Update&lt;/button&gt;
               &lt;button onclick="deleteData(${cursor.value.id})"&gt;Delete&lt;/button&gt;
                    `;
               cursor.continue();}};}functioncreateData(){const transaction = db.transaction(["myObjectStore"],"readwrite");const objectStore = transaction.objectStore("myObjectStore");const name = document.getElementById("name").value;const email = document.getElementById("email").value;const newData ={
            name: name,
            email: email
         };const request = objectStore.add(newData);
         request.onsuccess=()=&gt;{showData();cancelCreate();alert("Data added successfully")};
         request.onerror=()=&gt;{alert("Error creating data.");};}functionshowCreateForm(){
         document.getElementById("createForm").style.display ="block";}functioncancelCreate(){//if the user decides to not insert the record.
      document.getElementById("createForm").style.display ="none";
         document.getElementById("name").value ="";
         document.getElementById("email").value ="";}functionshowUpdateForm(id){const transaction = db.transaction(["myObjectStore"],"readwrite");const objectStore = transaction.objectStore("myObjectStore");const request = objectStore.get(id);
         request.onsuccess=(event)=&gt;{const data = event.target.result;if(data){const name =prompt("Update Name:", data.name);const email =prompt("Update Email:", data.email);if(name !==null&amp;&amp; email !==null){
                  data.name = name;
                  data.email = email;const updateRequest = objectStore.put(data);
                  updateRequest.onsuccess=()=&gt;{showData();alert("Updated data for "+data.name)};
                  updateRequest.onerror=()=&gt;{alert("Error updating data.");};}}};}functiondeleteData(id){const transaction = db.transaction(["myObjectStore"],"readwrite");const objectStore = transaction.objectStore("myObjectStore");const request = objectStore.delete(id);
         request.onsuccess=()=&gt;{showData();alert("Deleted data for id "+id)};
         request.onerror=()=&gt;{alert("Error deleting data.");};}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Try running the above program. In the output, you will get an interface to create, update, and delete data. The newly created or updated data will appear in tabular form just after the operation is finished.

  • Reference Type

    JavaScript Reference Type

    There are two types of data types in JavaScript: primitive and reference type.

    Primitive data types are immutable, which means that they cannot be changed. The primitive data types in JavaScript are: Number, String, Boolean, Undefined, Null, Symbol.

    Reference data types are mutable, which means that they can be changed. The reference data types in JavaScript are: Object, Array, Function.

    When you assign a primitive data type to a variable, the variable gets a copy of the value. When you assign a reference data type to a variable, the variable gets a reference to the value. This means that if you change the value of a reference data type, the change will be reflected in all of the variables that reference that value.

    For example, the following code creates two variables, x and y, and assigns them the value 10:

    let x =10;let y =10;

    The variables x and y both have a copy of the value 10. If you change the value of x, the value of y will not change.

    x =20;
    console.log(x);// 20
    console.log(y);// 10

    The following code creates two variables, x and y, and assigns them an array:

    const x =[1,2,3];const y = x;

    The variables x and y both reference the same array. If you change the value of the array that x references, the change will be reflected in the array that y references.

    x[0]=4;
    console.log(x);// [4, 2, 3]
    console.log(y);// [4, 2, 3]

    It is important to understand the difference between primitive and reference data types in JavaScript so that you can write code that is efficient and predictable.

    Objects and functions are the two main reference types in JavaScript and are explained as follows.

    Object

    Objects are unordered collections of key-value pairs, where keys are strings or symbols, and values can be any data type, including other objects.

    const person ={
      firstName:"John",
      lastName:"Doe",
      age:30};

    Function

    Functions are also reference types in JavaScript. Functions are special types of objects that can be invoked (called) to perform a task.

    functiongreet(name){alert("Hello, "+ name +"!");}

    Examples

    Example 1: Object Mutability

    In this example, we demonstrate object mutability for which first an object is created and then modifications are made through that reference which in turn affect the original object. The person object is modified via the reference from the anotherPerson precisely the age which is changed from 25 to 30. As seen in the output, the original object changes after the modification hence the object is said to be mutated.

    <!DOCTYPE html><html><body><h2>JavaScript Reference Types Example: Object Mutability</h2><script>// Create an objectconst person ={
    
         name:"John",
         age:25};// Create a reference to the objectlet anotherPerson = person;// Display the original object
      document.write("&lt;p&gt;Original Object: "+JSON.stringify(person)+"&lt;/p&gt;");// Modify the object through the reference
      anotherPerson.age =30;// Display the modified object
      document.write("&lt;p&gt;Modified Object: "+JSON.stringify(person)+"&lt;/p&gt;");// Both references point to the same object, so changes are reflected in both
      document.write("&lt;p&gt;Original Object after modification through reference: "+JSON.stringify(person)+"&lt;/p&gt;");&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 2: Array Modification

    Arrays which can store multiple values of different data types in JavaScript inside of a single variable are demonstrated here. They exhibit mutability which means then when a reference is made to an array, changes made to the reference also reflect in the original array. Here we create an array of colors and modify it through the reference of moreColors, mainly by pushing an element yellow.

    <!DOCTYPE html><html><body><h2>JavaScript Reference Types Example: Array Modification</h2><script>// Create an arrayconst colors =["red","green","blue"];// Create a reference to the array let moreColors = colors;// Display the original array
    
      document.write("&lt;p&gt;Original Array: "+JSON.stringify(colors)+"&lt;/p&gt;");// Modify the array through the reference
      moreColors.push("yellow");// Display the modified array
      document.write("&lt;p&gt;Modified Array: "+JSON.stringify(colors)+"&lt;/p&gt;");// Both references point to the same array, so changes are reflected in both
      document.write("&lt;p&gt;Original Array after modification through reference: "+JSON.stringify(colors)+"&lt;/p&gt;");&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 3: Function Reference Type

    In this example, we create a function greet whose reference is initially assigned to greetingFunction. After using it to say Hello, we modify the reference to point to a different function which greets with Hola. This demonstrated the flexibility of function references in JavaScript.

    <!DOCTYPE html><html><body><h2>JavaScript Reference Types Example: Function Invocation</h2><script>// Create a functionfunctiongreet(name){return"Hello, "+ name +"!";}// Create a reference to the functionlet greetingFunction = greet;
    
    
      document.write("&lt;p&gt;Original Function Result: "+greetingFunction("John")+"&lt;/p&gt;");greetingFunction=function(name){return"Hola, "+ name +"!";};
      document.write("&lt;p&gt;Modified Function Result: "+greetingFunction("Maria")+"&lt;/p&gt;");&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 4: Custom class

    This example demonstrated custom classes in JavaScript another crucial aspect from the point of view reference types. The class consists of properties and functions/methods. Here we create a class Book with a constructor and a method. 4 instances of this book class are created namely (book1, book2, book3, book4) and are given the respective data such as title, author and genre.

    <!DOCTYPE html><html><body><h2>JavaScript Reference Types Example: Custom class</h2><script>// Define a custom class for BookclassBook{constructor(title, author, genre){this.title = title;this.author = author;this.genre = genre;}// Method to get book detailsgetDetails(){returnTitle: ${this.title}&lt;br&gt;Author: ${this.author}&lt;br&gt;Genre: ${this.genre};}}// Create instances of the Book classconst book1 =newBook("The Great Gatsby","F. Scott Fitzgerald","Fiction");const book2 =newBook("To Kill a Mockingbird","Harper Lee","Classics");const book3 =newBook("Harry Potter and the Sorcerer's Stone","J.K. Rowling","Fantasy");const book4 =newBook("1984","George Orwell","Dystopian Fiction");
    
    
      document.write("&lt;h3&gt;Book 1 Details:&lt;/h3&gt;");
      document.write("&lt;p&gt;"+ book1.getDetails()+"&lt;/p&gt;");
      document.write("&lt;h3&gt;Book 2 Details:&lt;/h3&gt;");
      document.write("&lt;p&gt;"+ book2.getDetails()+"&lt;/p&gt;");
      document.write("&lt;h3&gt;Book 3 Details:&lt;/h3&gt;");
      document.write("&lt;p&gt;"+ book3.getDetails()+"&lt;/p&gt;");
      document.write("&lt;h3&gt;Book 4 Details:&lt;/h3&gt;");
      document.write("&lt;p&gt;"+ book4.getDetails()+"&lt;/p&gt;");&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Example 5: Immutable Objects

    This example focuses on immutability of objects which is achieved using the Object.freeze() while creating the object. Immutability basically means the object will not change after creation or simply ensures that once an object is defined, its properties cannot be modified. Here we create a person object with name & age as properties and then attempt to change the age to 35. However, this modification is prevented by the frozen state of the object and throws an error. Immutability is an important aspect as helps maintain data integrity thereby preventing unintended changes and enhancing the predictability in code execution.

    <!DOCTYPE html><html><body><h2>Immutable Object with Error Handling</h2><script>// Enable strict mode'use strict';// Create an immutable objectconst person = Object.freeze({
    
         name:"Alice",
         age:30});
      document.write("&lt;p&gt;&lt;strong&gt;Before Modification:&lt;/strong&gt;&lt;/p&gt;");
      document.write("&lt;p&gt;Name: "+ person.name +"&lt;/p&gt;");
      document.write("&lt;p&gt;Age: "+ person.age +"&lt;/p&gt;");try{// Attempting to modify the object will result in an error
         person.age =35;}catch(error){
         document.write(error);}
      document.write("&lt;p&gt;&lt;strong&gt;After Modification Attempt:&lt;/strong&gt;&lt;/p&gt;");
      document.write("&lt;p&gt;Name: "+ person.name +"&lt;/p&gt;");
      document.write("&lt;p&gt;Age: "+ person.age +"&lt;/p&gt;");&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

  • Call Stack

    JavaScript engine uses the call stacks to manage the execution context. It is an important mechanism by which a JavaScript run engine keeps track of the function calls in a JavaScript code. However, the working of the JavaScript call stack is performed internally, but it is important to understand how JavaScript executes the functions.

    JavaScript call stack keeps track of what function or block of code needs to run currently. It works in the LIFO (Last In, First Out) manner. So, whatever function is added at the top in the call stack it gets executed first.

    How JavaScript Call Stack Works?

    Whenever you execute any JavaScript code, it adds the global execution context to the script.

    When you call any function, the JavaScript engine adds the function to the call stack. After that, when you call any nested function from the outer function, it adds a nested function in the call stack.

    When the execution of the inner function is complete, it pops the function from the call stack. Next, it executes the outer function and pops it from the call stack. Again, it starts executing the code in the global context.

    When the call stack becomes empty, the script stops running.

    Let’s understand the JavaScript call stack via example.

    functiontwo(){
      console.log("this is function two");}functionone(){two();
      console.log("This is function one");}one();

    The above code would be executed like this.

    1. When the execution of the code starts, the call stack remains empty until execution reaches the one() function.

    2. Add function one() in the call stack. Now, the call stack is [one()].

    3. Execute the first line of function one(), which calls the function two().

    4. Add function two() in the call stack. Now, the call stack is [two(), one()].

    5. Execute all lines of function two().

    6. Move back to execute the remaining lines of code of function one().

    7. Delete the function two() from the call stack. Now, the call stack is [one()].

    8. Start executing the remaining code of the function one(). When the execution of function one() completes, the JavaScript engine starts executing the remaining code.

    9. Delete function one() from the call stack. Now, the call stack is empty.

    10. Execute the remaining code.

    Example

    Whenever we execute the below code, it will add the global execution context in the call stack. Whenever it calls any function from the global execution contest, it will add that function to the call stack, and start executing that function first.

    When another function is called from the particular function, it gets added to the call stack and gets priority for the execution.

    When the execution of the particular function is finished, the interpreter removes it from the call stack.

    Whenever a stack takes more space than its size, it throws the ‘stack overflow’ error.

    <html><body><h2> JavaScript - Call stack </h2><div id ="output"></div><script>const output = document.getElementById("output");functiontwo(){
    
        output.innerHTML +="two &lt;br&gt;";}functionone(){two();
        output.innerHTML +="one &lt;br&gt;";}one();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    JavaScript Call Stack Overflow

    Whenever the size of the call stack exceeds the defined size, a call stack overflow occurs. Generally, whenever a recursive function doesn't have an exit point call, a stack overflow occurs.

    For example, in the code below, the fib() function doesn't have an exit point. So, it throws a call stack overflow error.

    functionfib(){fib();}fib();

    Javascript is a single-thread programming language. So, it runs the code line-by-line from top to bottom. It means a JavaScript program can have only 1 call stack, and it can execute one line at a time.