Blog

  • Extending Errors

    The custom errors in JavaScript are errors that you create yourself, as opposed to the built-in errors that JavaScript throws. You can create custom errors to handle specific types of errors that may occur in your code.

    To create a custom error, you can use the Error constructor. The Error constructor takes a string as its argument, which will be the message of the error.

    Extending the Error Class: Creating Custom Errors

    The best way to create custom errors is by creating a new class and extending it using the ‘extends’ keyword. It uses the concept of inheritance, and the custom error class inherits the properties of the Error class.

    In the constructor() function, you can initialize the properties of the custom error class.

    Syntax

    You can follow the syntax below to create custom errors by extending the Error class.

    classcustomErrorextendsError{constructor(message){super(message)// Initialize properties}}

    In the above code, we call the parent class constructor using the super() method.

    You can also initialize the properties of the customError class in the constructor function.

    Example

    In the code below, we take the input from the user. When a user clicks the check age button, it calls the checkAge() function.

    We have defined the ageError class in JavaScript code and extended it with the Error class. In the ageError class, we have added the constructor() function to initialize the properties.

    In the constructor() function, we used the super() method to initialize the message property of the Error class. Also, we have initialized the ‘name’ and ‘age’ properties in the constructor function.

    In the checkAge() function, we throw the error if the age is less than 18, and in the catch{} block, we print the error message and age.

    <html><body><p>Enter your age:<input type ="number" id ="age"/></p><button onclick ="checkAge()"> Check Age </button><p id ="demo"></p><script>const output = document.getElementById("demo");classageErrorextendsError{constructor(message, age){super(message);this.name ="ageError";this.age = age // Custom property}}functioncheckAge(){const ageValue = document.getElementById('age').value;try{if(ageValue <18){// Throw error when age is less than 18thrownewageError("You are too young", ageValue);}else{
    
               output.innerHTML ="You are old enough";}}catch(e){
            output.innerHTML ="Error: "+ e.message +". &lt;br&gt;";
            output.innerHTML +="Age: "+ e.age +"&lt;br&gt;";}}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Enter your age: 5
    Check Age
    Error: You are too young.
    Age: 5
    

    If you want to create multiple new classes for the custom errors only to provide the clarified error type and message and don't want to change the properties of the Error class, you can use the syntax below.

    classInputErrorextendsError{};

    Let's learn it via the example below.

    Example

    In the code below, we have created 3 different custom classes and extended them with the Error class to create custom errors.

    In the try{} block, we throw the StringError.

    In the catch{} block, we used the instanceOf operator to check the type of the error object and print the error message accordingly.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");classStringErrorextendsError{};classNumberErrorextendsError{};classBooleanErrorextendsError{};try{thrownewStringError("This is a string error");}catch(e){if(e instanceofStringError){
    
            output.innerHTML ="String Error";}elseif(e instanceofNumberError){
            output.innerHTML ="Number Error";}elseif(e instanceofBooleanError){
            output.innerHTML ="Boolean Error";}else{
            output.innerHTML ="Unknown Error";}}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    String Error
    

    Multilevel Inheritance

    You can create a general custom error by extending it with the Error class. After that, you can extend the custom error class to create a more generalized error class.

    Let's understand it via the example below.

    Example

    In the code below, we have defined the 'NotFound' class and extended it using the Error class.

    After that, we defined the 'propertyNotFound' and 'valueNotFound' classes and extended them with the 'NotFound' class. Here, we have done the multilevel inheritance.

    In the try block, we throw a valueNotFound error if the array doesn't contain 6.

    In the catch block, we print the error.

    <html><body><div id ="output"></div><script>const output = document.getElementById("output");classNotFoundextendsError{constructor(message){super(message);this.name ="NotFound";}}// Further InheritanceclasspropertyNotFoundextendsNotFound{constructor(message){super(message);this.name ="propertyNotFound";}}// Further InheritanceclassElementNotFoundextendsNotFound{constructor(message){super(message);this.name ="ElementNotFound";}}try{let arr =[1,2,3,4,5];// Throw an error if array doesn't contain 6if(!arr.includes(6)){thrownewpropertyNotFound("Array doesn't contain 6");}}catch(e){
    
         output.innerHTML = e.name +": "+ e.message;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    propertyNotFound: Array doesn't contain 6
    

    You can also throw the propertyNotFound error if any object doesn't contain the particular property.

  • Custom Errors

    Custom errors are a way to create user-defined error types in JavaScript. This can be useful for handling specific types of errors, such as database errors or HTTP errors.

    JavaScript contains multiple built-in objects for the errors. Whenever any error occurs in the JavaScript code, it throws an instance of the Error class. However, you can also throw the instance of the Error class with a custom message using the ‘throw’ statement.

    In some conditions, developers need to create custom errors. For example, you are taking the user’s age in the input. If the user’s age is not above 18, you can throw a custom error like ‘ageNotValid’ for more clarification.

    Let’s understand the syntax of the Error class first, and then you will learn to create custom errors.

    The Error Class

    In JavaScript, Error is a generic class for the errors. You can create an instance of the Error class and pass the custom message as an argument.

    The Error class contains three properties: name, message, and stack.

    So, you can assume the syntax of the Error class as shown below.

    classError{constructor(message){this.message = message;this.name ="Error";this.stack =<call stack>;}}

    The ‘stack’ property is a non-standard property in the above syntax. It is supported by the Firefox browser only.

    Creating Custom Errors Using the Instance of the Error Class

    The easiest way to create a custom error is to create an instance of the Error class and change its properties.

    Syntax

    You can follow the syntax below to create custom errors by changing the properties of the instance Error class.

    const customError =newError(message);
    customError.name ="CustomError";

    Here, we have created the ‘Error’ class instance and passed the ‘message’ as an argument. Also, we have changed the value of the ‘name’ property. Similarly, you can change the value of the ‘message’ property if you don’t want to pass it as an Error() constructor argument.

    Parameter

    • message − It is a text message to represent the error.

    Example

    In the code below, we have created the instance of the Error class and stored it in the ‘customError’ variable. After that, we changed the value of the ‘name’ property to the ‘CustomError’.

    In the try{} block, we have used the ‘throw’ statement to throw the custom error, and in the catch{} block, we print the error name and message.

    <html><body><div id ="output"></div><script>const customError =newError("This is a custom error");
    
      customError.name ="CustomError";try{throw customError;}catch(err){
         document.getElementById("output").innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    CustomError: This is a custom error
    

    Creating the Custom Errors Using the Function Constructor

    You can use the function constructor to create the template for the object. The function constructor should contain the 'name' and 'message' properties.

    Next, you can change the prototype of the function constructor with the prototype of the Error class.

    Syntax

    You can follow the syntax below to create custom errors using the constructor of the function class.

    functionvalidationError(messag, name){this.message = messag;this.name = name;}
    validationError.prototype =Error.prototype;

    In the above syntax, we have defined the validationError() function, taking the message and name as a parameter. After that, we initialize the message and name properties of the function with parametric values.

    Next, we change the prototype of the function with the prototype of the Error class.

    Example

    In the code below, we have defined the validationError() function constructor and inherited it using the prototype of the Error class.

    In the try{} block, we have defined the 'str' variable and initialized it with the numeric value. After that, we validate the type of the 'str' variable using the typeof operator. If it is not a string, we throw 'validationError' by passing the message and name as an argument.

    In the catch{} block, we print the message on the web page. You can run the code, and observe the error in the output.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");functionvalidationError(message ="", name ="validationError"){this.message = message;this.name = name;}
    
      validationError.prototype =Error.prototype;try{let str =10;if(typeof str !="string"){thrownewvalidationError("Not a string","NotStringError");}else{
            output.innerHTML ="String is valid";}}catch(e){
         output.innerHTML = e.name +": "+ e.message;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    NotStringError: Not a string
    

    Creating Custom Errors by Extending the Error Class

    The best way to create custom errors is by creating a new class and extending it using the 'extends' keyword. It uses the concept of inheritance, and the custom error class inherits the properties of the Error class.

    In the constructor() function, you can initialize the properties of the custom error class.

    Syntax

    You can follow the syntax below to create custom errors by extending the Error class.

    classCustomErrorextendsError{constructor(message){super(message)// Initialize properties}}

    In the above code, we call the parent class constructor using the super() method.

    You can also initialize the properties of the CustomError class in the constructor function.

    You can use any of the above approaches to create custom errors according to your requirements.

  • Debugging

    What is Debugging?

    Debugging in JavaScript is a process of examining JavaScript code and finding erros and fixing them. Every now and then, developers commit mistakes while coding. This error can be logical, syntax, or runtime errors. An error in a program or a script is referred to as a bug.

    The process of finding and fixing bugs is called debugging and is a normal part of the development process. This section covers tools and techniques that can help you with debugging tasks.

    Let’s look at the different methods of debugging.

    Use a JavaScript Debugger

    A debugger is an application that places all aspects of script execution under the control of the programmer. Debuggers provide fine-grained control over the state of the script through an interface that allows you to examine and set values as well as control the flow of execution.

    Once a script has been loaded into a debugger, it can be run one line at a time or instructed to halt at certain breakpoints. Once execution is halted, the programmer can examine the state of the script and its variables in order to determine if something is amiss. You can also watch variables for changes in their values.

    Nowadays, all modern browser comes with built-in debuggers. You can use the console of the browser to debug the JavaScript code.

    How to Open Console in the Browser?

    In this section, you will learn to open the console in different browsers.

    Press the Below keys.

    • Windows/Linux − Ctrl + Shift + I or Ctrl + Shift + J
    • macOs − Cmd + Option + I or Cmd + Option + J

    OR

    • Step 1 − Open Chrome web browser and open the web page in a new window.
    • Step 2 − Right-click anywhere on the web page.
    • Step 3 − It will pop up menu. Select the last option, which is ‘inspect’.
    • Step 4 − It will open a Chrome developer tool.
    • Step 5 − Go to the console tab.

    Press the Below keys.

    • Windows/Linux − Ctrl + Shift + I or Ctrl + Shift + J
    • macOs − Cmd + Option + I or Cmd + Option + J

    OR

    • Step 1 − Open Firefox web browser and open the web page in a new window.
    • Step 2 − Right-click anywhere on the web page.
    • Step 3 − Select the last option from the popup menu, which is ‘inspect(Q)’.
    • Step 4 − It will open a developer tool.
    • Step 5 − You can move from the ‘inspector’ tab to the ‘console’ tab.

    Press the Below keys.

    • Windows/Linux − Ctrl + Shift + I or Ctrl + Shift + J
    • macOs − Cmd + Option + I or Cmd + Option + J

    OR

    • Step 1 − Open the Microsoft Edge browser.
    • Step 2 − Right-click anywhere on the web page.
    • Step 3 − Click on ‘inspect’ in the popup menu.
    • Step 4 − You will see the developer tool is opened.
    • Step 5 − Next, you can change the ‘Elements’ tab to the ‘Console’ tab in the developer tool.

    Press the Below keys.

    • Windows/Linux − Ctrl + Shift + I or Ctrl + Shift + J
    • macOs − Cmd + Option + I or Cmd + Option + J

    OR

    • Step 1 − Open the Safari web browser.
    • Step 2 − Open the Safari main menu from the top menu bar.
    • Step 3 − Choose ‘preferences’ in the dropdown menu. Next, choose the ‘advanced’ option.
    • Step 4 − Check the checkbox named ‘Enable Show Develop menu in menu bar’ to enable the developer tool. Next, close the preference window.
    • Step 5 − Next, reopen the main menu and select ‘Develop. After that, select the ‘Show Error Console.

    Press the Below keys.

    • Windows/Linux − Ctrl + Shift + I or Ctrl + Shift + J
    • macOs − Cmd + Option + I or Cmd + Option + J

    OR

    • Step 1 − Open the Opera browser.
    • Step 2 − Open the main menu from the top corner.
    • Step 3 − In the main menu, select the ‘Developer. It will open the sub-menu.
    • Step 4 − In the submenu, select the ‘developer tools.
    • Step 5 − Next, select the ‘console. It will open a console.

    Using the console.log() method

    The console.log() method prints the message in the web browser’s console. It can print primitive values, objects, variable values, etc.

    You can print the variable’s value in the console you want to debug.

    Syntax

    Users can follow the syntax below to use the console.log() method.

    Console.log(val1, val2,...);

    The console.log() method takes the comma-separated arguments to print in the web browser’s console.

    Example

    In the code below, we add the value of the num1 and num2 variables. In the browser, you can see that the sum is 32 rather than 5.

    So, you are required to debug the code.

    When you print the type of the num1 and num2 into the console, it shows that the type of the num1 is a string. So, it converts the value of the num2 variable into the string and appends it with the value of the num1.

    <html><body><div id ="output"></div><p>Note: To see the resullt in console, please open it before you run the code.</p><script>let num1 ="3";let num2 =2;let sum = num1 + num2;
    
      document.getElementById("output").innerHTML ="The sum is: "+ sum;
      console.log("typeof num1 is "+typeof num1);
      console.log("typeof num2 is "+typeof num2);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The sum is: 32
    Note: To see the resullt in console, please open it before you run the code.
    

    It will produce the following result in the web console −

    typeof num1 is string
    VM75616:7 typeof num2 is number
    

    Example

    In the code below, we have a person object containing various properties. We print the firstname and lastname properties of the person object in the web browser. It prints undefined.

    To find the error, you are required to debug the code. Next, we print the object in the console and found that the Person object doesn't contain the firstname and lastname properties; instead of that, it contains the 'name' property.

    <html><body><div id ="demo"></div><p>Note: To see the resullt in console, please open it before you run the code.</p><script>let output = document.getElementById("demo");let person ={
    
         name:"John",
         age:25,
         city:"New York"}
      output.innerHTML ="The name of the person is: "+ person.name +"&lt;br&gt;";
      output.innerHTML +="The city of the person is: "+ person.city +"&lt;br&gt;";
      console.log(person);&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The name of the person is: John
    The city of the person is: New York
    Note: To see the resullt in console, please open it before you run the code.
    

    It will produce the following result in the web console −

    {name: 'John', age: 25, city: 'New York'}
    

    Using the debugger Keyword

    You can go to your browser's console's 'source' panel to debug the code.

    The 'debugger' keyword allows you to force-stop the execution of the JavaScript code.

    Stopping the execution of the JavaScript code allows you to debug the code line-by-line.

    Once you find the bug or everything looks fine, you can resume the execution of the JavaScript code.

    You can open the console and run the below code in the browser. It will automatically pause the code, and you can observe the values of the variables to debug the code.

    Example

    The below example is the same as above. We have added the 'debugger' keyword before it prints the values of the object properties.

    It will pause the execution of the code before printing the values of properties. After that, when you click on the resume button, it will resume the execution of the code.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");const person ={
    
         name:"John",
         age:25,
         city:"New York"}debugger;
      output.innerHTML ="The name of the person is: "+ person.name +"&lt;br&gt;";
      output.innerHTML +="The city of the person is: "+ person.city;&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The name of the person is: John
    The city of the person is: New York
    

    You will see the result in console similar to the below screenshot. To see the resullt in console, please open it before you run the code.

    Debugger Keyword

    The above image shows the pause button at the top of the browser window and the object or variables in the bottom-right corner. This way, you can check variable values and debug the code to fix the bugs.

    Setting Break Points in the Browser's Debugger

    Setting up breakpoints is the same as using the 'debugger' keyword to debug the JavaScript code. So, this is an alternative way.

    In the 'source' panel, you can click on the line number where you want to add a breakpoint, as shown in the image below.

    After that, when you execute the JavaScript code, it will stop the execution of the code, and you can observe the variable values on the right side.

    Debugging break point

    Example

    We have defined the test() function in the example code below. The test() function concatenates the str1 and str2 strings.

    We have opened the 'source' panel in the browser in the developer tool. After that, we have added the breakpoint on the line 'let res = str1.concat(str2);'. So, the debugger will stop the execution of the code at this line, and you can click the resume button to resume the execution of the code.

    <html><body><div id ="output">The resultant string after appending str2 to str1 is:</div><script>functiontest(){let str1 ="Hi";let str2 ="";let res = str1.concat(str2);
    
         document.getElementById("output").innerHTML += res;}test();&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The resultant string after appending str2 to str1 is: Hi
    

    You will see the result in console similar to the below screenshot. To see the resullt in console, please open it before you run the code.

    Debugging break point output

    Useful Tips for Developers

    You can keep the following tips in mind to reduce the number of errors in your scripts and simplify the debugging process −

    • Use plenty of comments. Comments enable you to explain why you wrote the script the way you did and to explain particularly difficult sections of code.
    • Always use indentation to make your code easy to read. Indenting statements also makes it easier for you to match up beginning and ending tags, curly braces, and other HTML and script elements. You can use the code formatters in the IDE.
    • Write modular code. Whenever possible, group your statements into functions. Functions let you group related statements and test and reuse portions of code with minimal effort.
    • Be consistent in the way you name your variables and functions. Try using names that are long enough to be meaningful and that describe the variable's contents or the function's purpose.
    • Use consistent syntax when naming variables and functions. In other words, keep them all lowercase or all uppercase; if you prefer Camel-Back notation, use it consistently.
    • Test long scripts in a modular fashion. In other words, do not try to write the entire script before testing any portion of it. Write a piece and get it to work before adding the next portion of code.
    • Use descriptive variable and function names and avoid using single-character names.
    • Watch your quotation marks. Remember that quotation marks are used in pairs around strings and that both quotation marks must be of the same style (either single or double).
    • Watch your equal signs. You should not use a single = for comparison purposes.
    • Declare variables explicitly using the var keyword.
  • try catch

    JavaScript try…catch Statement

    The try-catch statement in JavaScript is used to handle the runtime errors (exceptions). This is very common in most programming languages to handle exceptions. A try-catch statement can handle only runtime errors. The try block must be followed by either exactly one catch block or one finally block (or one of both).

    Inside the try{} statement, you can write the code having errors or possibilities of the errors. You can add regular JavaScript code into the try{} statement.

    The catch{} statement is used to handle the errors. When any error occurs in the code of the try{} statement, the JavaScript run engine executes the code of the catch{} statement to handle the errors.

    If no error occurs in the code of the try{} statement, it will skip the code of the catch{} statement and execute the next lines of the code.

    Syntax

    You can follow the syntax below to use the try-catch statements in the code to handle exceptions.

    try{// JavaScript code}catch(error){// Handle error}

    You can print the error object in the catch{} statement or the custom error message based on the error type to show errors.

    Parameters

    • error − The catch{} statement takes the error object as a parameter. It contains the name and message property. However, it is an optional parameter.

    Example

    In the code below, we assign the num1 variables value to the num variable inside the try{} statement. Here, the num1 variable is not defined. So, it will throw an error.

    In the catch{} statement, we print the value of the error object’s name and message property.

    In the output, you can observe that it throws a reference error with a proper error message.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{let num = num1;}catch(err){
    
         output.innerHTML +="The error name is: "+ err.name +"&lt;br&gt;";
         output.innerHTML +="The error message is: "+ err.message +".&lt;br&gt;";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The error name is: ReferenceError
    The error message is: num1 is not defined.
    

    When any error occurs in the try{} statement, it skips the execution of the remaining code and executes the code of the catch{} statement.

    Lets understand it via the example below.

    Example

    In the code below, we invoke the welcome() function, which is not defined. So, it will throw a reference error.

    In the catch{} statement, we handle the error.

    In the output, you can see that it prints the start message of the try{} statement, the start message of the catch{} statement, and the error message. It skips the end message of the try{} statement as an error occurs before that.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{
    
         output.innerHTML +="In the start of try block &lt;br&gt;";welcome();
         output.innerHTML +="In the end of try block &lt;br&gt;";}catch(err){
         output.innerHTML +="In the catch block &lt;br&gt;";
         output.innerHTML +="The error name is: "+ err.name +"&lt;br&gt;";
         output.innerHTML +="The error message is: "+ err.message +".&lt;br&gt;";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    In the start of try block
    In the catch block
    The error name is: ReferenceError
    The error message is: welcomeis not defined.
    

    Note − The try-catch statement doesnt allow you to handle the syntax errors. It can handle only runtime errors.

    For example, if you run the below code. It will show you an error in the browsers console but cant catch the error using the {} statement.

    try{let num =;}catch(err){// Error handling}

    JavaScript trycatchfinally Statement

    The finally{} statement allows you to execute the particular code after completing the execution of the try{} and catch{} statements.

    JavaScript always executes the code of the finally{} statement, whether the error occurs in the code of the try{} statement. If an error occurs, it executes the code of the catch{} statement and then executes the code of the finally{} statement.

    Example

    In the code below, we assign the value of the variable 'b' to the variable 'a' inside the try{} statement. It throws an error.

    In the catch{} statement, we print the error.

    In the finally{} statement, it prints the message.

    You can observe the output that it runs the code of the try{} statement first, the code of the catch{} statement after that, and the code of the finally{} statement at last.

    <html><body><div id ="output"></div><script>try{let a = b;}catch(e){
    
         document.getElementById("output").innerHTML = e;}finally{
         document.getElementById("output").innerHTML +="&lt;br&gt;Finally block always executes";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    ReferenceError: b is not defined
    Finally block always executes
    

    Example

    In the example below, we have written the code without any error into the try{} statement.

    Also, we have added the catch{} and finally{} statements.

    The output shows that it executes the try{} statement code and finally{} statement code after that. It skips the execution of the catch{} statement, as the code is error-free.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{let a =10;
    
         output.innerHTML ="Value of a is "+ a +"&lt;br&gt;";}catch(e){
         output.innerHTML = e.name +" : "+ e.message;}finally{
         output.innerHTML +="Inside the finally block.";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Value of a is 10
    Inside the finally block.
    

    JavaScript Throw Statement

    When any error occurs in the code, JavaScript throws an error by default. But you can also throw the error manually. For example, you are doing the form data validation. If the data is invalid, you can throw the error and ask users to correct the data.

    When you throw an error using the throw statement, the code present after that in the try{} statement will not executed, and it will execute the code of the catch{} statement.

    You can follow the syntax below to throw an error using the throw statement.

    throw<error>;

    In the above syntax, <error> can be a Error object, string, number, primitive value, or a particular type of error object. It is a good practice to throw an Error object rather than throwing the primitive value.

    Example: Throwing the Error object

    In the code below, we throw an Error object from the try{} statement using the throw statement. It stops the execution of the remaining code of the throw statement and executes the code of the catch{} statement.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{
    
         output.innerHTML +="Start of the try block. &lt;br /&gt;";thrownewError("Custom error");
         output.innerHTML +="End of the try block. &lt;br /&gt;";//not executed}catch(e){
         output.innerHTML +="Catch block: Caught exception. &lt;br /&gt;";
         output.innerHTML += e.name +" : "+ e.message;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Start of the try block
    Catch block: Caught exception.
    Error: Custom error
    

    Example: Throwing the primitive value

    In the code below, we throw the primitive numeric value from the try{} statement. In the catch{} statement, we get the thrown primitive value and print it.

    <html><body><div id ="output">The error message is:</div><script>try{throw20;}catch(e){
    
         document.getElementById("output").innerHTML += e;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The error message is: 20
    

    Example: Input Validation Example

    In the code below, we have defined the <input> element of the number type to take the user age as an input.

    When the user clicks the submit age button, it invokes the handleAge() function. The handleAge() function checks whether the age is less than 18. If yes, it throws the rangeError.

    The catch{} statement prints the error message to validate the age.

    <html><body><p>Age:<input type ="number" id ="age" value ="20"></p><button onclick ="handleAge()"> Submit Age </button><p id ="demo"></p><script>const output = document.getElementById("demo");functionhandleAge(){let age = document.getElementById("age").value;try{if(age <18){throwRangeError("You are not eligible to vote");}else{
    
               output.innerHTML +="&lt;br&gt;You are eligible to vote";}}catch(e){
            output.innerHTML +="&lt;br&gt;The error is - "+ e;}}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Age: 20
    Submit Age
    The error is - RangeError: You are not eligible to vote
    

    Nesting Try Blocks

    Sometimes, developers are required to write the nested try-catch statements. The nested try-catch means a try block inside the try block.

    If the inner catch{} statement cant handle the error, the outer catch{} statement may handle it. You can also skip the inner catch{} statement, but in this case, you need to write the finally{} statement with the try{} statement.

    Example

    We have used the two nested try{} statements in the code below. We have added the try-finally statement inside the outer try{} statement.

    The inner try{} statement throws the error, handled in the outer catch{} statement.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{try{throwError("Error in the inner try block");}finally{
    
            output.innerHTML +="Inside the inner finally block. &lt;br&gt;";}}catch(e){
         output.innerHTML +="Inside the outer catch block. &lt;br&gt;";
         output.innerHTML +="Error: "+ e.message;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Inside the inner finally block.
    Inside the outer catch block.
    Error: Error in the inner try block
    

    The Rethrow Error

    Sometimes, it can happen that the catch{} statement cant handle the error. In such cases, you can rethrow the error from the catch block using the throw statement.

    The outer catch{} statement can handle the rethrown error if it is available.

    Example

    In the code below, we have created the two nested try-catch blocks. In the inner try block, we throw the error using the throw statement. The inner catch{} statement will catch the error, and we rethrow the error from the inner catch{} statement.

    After that, we handle the error in the outer catch{} statement.

    <html><body><div id ="demo"></div><script>let output = document.getElementById("demo");try{try{throw20;}catch(e){// Rethrowing the error.
    
            output.innerHTML ="Inside the inner catch block. &lt;br&gt;";
            output.innerHTML +="Error: "+ e +"&lt;br&gt; &lt;br&gt;";throw e;}}catch(e){
         output.innerHTML +="Inside the outer catch block. &lt;br&gt;";
         output.innerHTML +="Error: "+ e;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    inside the inner catch block.
    Error: 20
    
    Inside the outer catch block.
    Error: 20
    

    Conditional Catch-blocks

    Inside the catch{} block, you can use the if-else statement to handle the errors conditionally. In this way, you can use the single catch{} statement for the multiple try{} statements.

    In the catch{} statement, you can check the type of the error using the instanceOf operator and handle the error according to the error type.

    Example

    In the code below, we have called the welcome function inside the try{} statement, and the welcome() function is not defined.

    In the catch{} statement, we check the type of the error using the instanceOf operator and print the message on the web page according to the type of the error.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{welcome();// Function not defined}catch(e){if(e instanceofReferenceError){
    
            output.innerHTML ="Reference error is occurred.";}elseif(e instanceofTypeError){
            output.innerHTML ="Type error is occurred.";}elseif(e instanceofRangeError){
            output.innerHTML ="Range error is occurred.";}elseif(e instanceofSyntaxError){
            output.innerHTML ="Syntax error is occurred.";}else{
            output.innerHTML ="Error is occurred.";}}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Reference error is occurred.
    

    JavaScript try...catch with setTimeout() Method

    Using the try-catch statement with the asynchronous JavaScript code wont catch the error thrown from the try block.

    The reason is that JavaScript executes the asynchronous code, when all main thread code gets executed.

    Lets understand it via the example below.

    Example

    In the code below, we used the setTimeOut() method inside the try{} statement. It executes the callback function after 1000 milliseconds. In the callback function, we throw the error using the throw statement.

    In the output, you can observe that the cathc{} statement is not catching the error, and it prints the error in the browsers console.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");try{
    
         output.innerHTML ="Inside the try block. &lt;br&gt;";setTimeout(()=&gt;{thrownewError("Whoops!");},1000);}catch(err){
         output.innerHTML +="Inside the catch block. &lt;br&gt;";
         output.innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Inside the try block.
    

    Promise-based Errors

    When any error occurs while consuming the promise code, you can use the catch() method to handle the error. Alternatively, you can pass the error handler as a second parameter of the then() method.

    Examples

    In the code below, we have created the promise and rejected it after 1000 milliseconds.

    After that, we used the then() and catch() method to handle the promise. Here, we have rejected the promise so that control will execute the code of the catch() method.

    <html><body><div id ="demo"></div><script>const output = document.getElementById("demo");
    
      output.innerHTML ="The promise is pending...";let promise =newPromise((resolve, reject)=&gt;{setTimeout(()=&gt;{reject("The promise is rejected!");},1000);});
      promise
      .then((result)=&gt;{
         output.innerHTML = result;}).catch((error)=&gt;{
         output.innerHTML = error;});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    The promise is rejected !
    

    Types of Errors in JavaScript

    There are different types of errors that JavaScript can throw. Here, we will learn each type one by one with examples.

    JavaScript Range Error

    The JavaScript code throws a range error when the value is out of the specified range.

    Example

    In the code below, we used the toPrecision() method and passed 1000 as an argument. It throws the range error, as the number cant have 1000 digits.

    <html><body><div id ="output"></div><script>try{let num =10;
    
         num.toPrecision(1000);}catch(err){
         document.getElementById("output").innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    RangeError: toPrecision() argument must be between 1 and 100
    

    JavaScript Reference Error

    The reference error occurs when you try to access the undefined variables, functions, class methods, etc.

    Example

    In the code below, we execute the test() method of the window object. Here, the test() method is not defined, so it throws the reference error.

    <html><body><div id ="output"></div><script>try{
    
         window.test();}catch(err){
         document.getElementById("output").innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    TypeError: window.test is not a function
    

    JavaScript Type Error

    The JavaScript code throws the type error if you dont use the values of the valid type with methods or operators.

    Example

    In the example below, we use the toLowerCase() method with the boolean variable, but the toLowerCase() method is supported by string values only. So, it throws the type error.

    <html><body><div id ="output"></div><script>try{let bool =true;
    
         bool.toLowerCase();}catch(err){
         document.getElementById("output").innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    TypeError: bool.toLowerCase is not a function
    

    JavaScript URI (Uniform Resource Identifier) Error

    The URI error occurs when you dont pass the valid URL as an argument of the encodeURI, decodeURI, etc. methods.

    Example

    In the example below, we passed the invalid encoded URI as an argument of the decodeURI() method. So, it throws the URIError.

    <html><body><div id ="output"></div><script>try{decodeURI("%");}catch(err){
    
         document.getElementById("output").innerHTML = err;}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    URIError: URI malformed

  • Errors & Exceptions Handling

    Error handling in JavaScript is a process to detect and handle errors that occurs during the execution of a program. Errors can be a syntax, runtime or logical errors. An error occurred during the execution of the program is called a runtime error or an exception.

    In JavaScript, errors can occur due to programming mistakes, incorrect user input, etc. Errors can disrupt code execution and lead to bad user experience. Effective error & exception handling is required for building robust, reliable and user friendly applications in JavaScript.

    What is an Error?

    An error is an event that occurs during the execution of a program that prevents it from continuing normally. Errors can be caused by a variety of factors, such as syntax errors, runtime errors, and logical errors.

    Syntax Errors

    Syntax errors, also called parsing errors, occur at compile time in traditional programming languages and at interpret time in JavaScript.

    For example, the following line causes a syntax error because it is missing a closing parenthesis.

    <script>
       window.print();</script>

    When a syntax error occurs in JavaScript, only the code contained within the same thread as the syntax error is affected, and the rest of the code in other threads gets executed, assuming nothing in them depends on the code containing the error.

    Runtime Errors (Exceptions)

    Runtime errors, also called exceptions, occur during execution (after compilation/interpretation).

    For example, the following line causes a runtime error because the syntax is correct here, but at runtime, it is trying to call a method that does not exist.

    <script>
       window.printme();</script>

    Exceptions also affect the thread in which they occur, allowing other JavaScript threads to continue normal execution.

    There are many JavaScript runtime errors (exceptions), some are as follows −

    • ReferenceError − Trying to access an undefined variable/ method.
    • TypeError − Attempting an operation on incompatible data types.
    • RangeError − A value exceeds the allowed range.

    Logical Errors

    Logic errors can be the most difficult type of errors to track down. These errors are not the result of a syntax or runtime error. Instead, they occur when you make a mistake in the logic that drives your script and do not get the expected result.

    For example, when you divide any numeric value with 10, it returns undefined.

    <script>let num =10/0;</script>

    What is Error Handling?

    Whenever any error occurs in the JavaScript code, the JavaScript engine stops the execution of the whole code. If you handle such errors in the proper way, you can skip the code with errors and continue to execute the other JavaScript code.

    You can use the following mechanisms to handle the error.

    • try…catch…finally statements
    • throw statements
    • the onerror() event handler property
    • Custom Errors

    The try…catch…finally Statement

    The latest versions of JavaScript added exception handling capabilities. JavaScript implements the try…catch…finally construct as well as the throw operator to handle exceptions.

    You can catch programmer-generated and runtime exceptions, but you cannot catch JavaScript syntax errors.

    Here is the try…catch…finally block syntax −

    <script>try{// Code to run[break;]}catch( e ){// Code to run if an exception occurs[break;]}[finally{// Code that is always executed regardless of // an exception occurring}]</script>

    The try block must be followed by either exactly one catch block or one finally block (or one of both). When an exception occurs in the try block, the exception is placed in e and the catch block is executed. The optional finally block executes unconditionally after try/catch.

    Example

    Here is an example where we are trying to call a non-existing function which in turn is raising an exception.

    Let us try to catch this exception using try…catch and display a user-friendly message. You can also suppress this message, if you want to hide this error from a user.

    You can use finally block which will always execute unconditionally after the try/catch.

    <html><head><script>try{var a =100;alert(myFunc(a));}catch(e){alert(e);}finally{alert("Finally block will always execute!");}</script></head><body><p>Exception handling using try...catch...finally statements</p></body></html>

    Output

    Exception handling using try...catch...finaly statements
    

    The throw Statement

    You can use throw statement to raise your built-in exceptions or your customized exceptions. Later these exceptions can be captured and you can take an appropriate action.

    Example

    The following example demonstrates how to use a throw statement.

    <html><head><script>functionmyFunc(){var a =100;var b =0;try{if( b ==0){throw("Divide by zero error.");}else{var c = a / b;}}catch( e ){alert("Error: "+ e );}}</script></head><body><p>Click the following to see the result:</p><form><input type ="button" value ="Click Me" onclick ="myFunc();"/></form></body></html>

    Output

    Click the following to see the result:
    Click Me
    

    You can raise an exception in one function using a string, integer, Boolean, or an object and then you can capture that exception either in the same function as we did above, or in another function using a try…catch block.

    The onerror Event Handler Property

    The onerror event handler was the first feature to facilitate error handling in JavaScript. The onerror is an event handler property of the ‘window’ object, which automatically triggers when any error occurs on any element of the web page. You can call the callback function when any error occurs to handle the error.

    You can follow the syntax below to use the onerror event handler property.

    window.onerror = errorhandler_func;OR<ele onerror="errorhandler_func()"></ele>

    In the above syntax, errorhandler_func() will be executed when any error will occur.

    The onerror event handler provides three pieces of information to identify the exact nature of the error −

    • Error message − The same message that the browser would display for the given error
    • URL − The file in which the error occurred
    • Line number − The line number in the given URL that caused the error

    Example

    In the code below, we added the onclick event on the <input> element, and we called the myFunc() function when users click the input element. The myFunc() function is not defined. So, it will throw an error.

    We used the ‘onerror’ event handler to catch the error. In the callback function, we print the error message, file URL, and line number in the file where the error occurs.

    <html><body><p> Click the following button to see the result:</p><form><input type ="button" value ="Click Me" onclick ="myFunc();"/></form><div id ="demo"></div><script>const output = document.getElementById("demo");
    
      window.onerror=function(msg, url, line){
         output.innerHTML ="Error: "+ msg +"&lt;br&gt;";
         output.innerHTML +="URL: "+ url +"&lt;br&gt;";
         output.innerHTML +="Line: "+ line +"&lt;br&gt;";}&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Output

    Click the following button to see the result:
    Click Me
    Error: Uncaught ReferenceError: myFunc is not defined
    URL: file:///C:/Users/Lenovo/Desktop/intex.html
    Line: 5
    

    You can use an onerror method, as shown below, to display an error message in case there is any problem in loading an image.

    <img src="myimage.gif" onerror="alert('An error occurred loading the image.')"/>

    You can use onerror with many HTML tags to display appropriate messages in case of errors.

    The JavaScript Error Class and Error Object

    Whenever any error occurs in the code, JavaScript throws an instance (object) of the error class. The error object contains the information about the error.

    However, Error() is a generic constructor for all types of errors, but different objects exist for different types of errors.

    JavaScript Custom Errors

    You can also throw an error with the custom message using the Error() constructor.

    const customError =newError(message);
    customError.name ="CustomError";

    Here, we have created the 'Error' class instance and passed the 'message' as an argument. Also, we have changed the value of the 'name' property. Similarly, you can change the value of the 'message' property if you don't want to pass it as an Error() constructor argument.

    JavaScript Error Object Reference

    JavaScript Error Types or Constructor

    JavaScript contains the below types of errors. You can also use it as a constructor to create a new error of the specific type.

    Error Type/ObjectDescription
    ErrorIt is a generic constructor for the error. You can also create custom errors by extending the Error object.
    SyntaxErrorThe instance of the SyntaxError is thrown when any error is in the syntax. For example, missing parenthesis, invalid JSON, etc.
    ReferenceErrorThe reference error occurs when you try to access variables not defined in the current scope.
    TypeErrorWhen the types of the variables is not valid, JavaScript throws the type error.
    RangeErrorWhen numeric input is out of range, it throws the range error.
    URIErrorJavaScript throws the URIError when you pass invalid arguments to the decodeURI or encodeURI methods.
    EvalErrorDeprecated.
    AggregateErrorIt is used to aggregate multiple error objects into a single error object, and it allows you to handle multiple error objects.

    Error Object Properties

    The Error object contains the two properties.

    PropertyDescription
    nameIt is used to set or get an error name.
    messageIt is used to set or get an error message.

    Non-Standard Properties and Methods

    Here is the list of the non-standard properties and methods of the Error object. However, they are not supported by all browsers. So, you should avoid using them.

    PropertyDescription
    columnNumberIt is supported in the Firefox browser only.
    descriptionIt is supported in the Microsoft browser only.
    displayNameIt is supported in the Firefox browser only.
    fileNameIt is supported in the Firefox browser only.
    lineNumberIt is supported in the Firefox browser only.
    numberIt is supported in the Microsoft browser only.
    stackIt is supported in the Firefox browser only.
    internalError()It is supported in the Firefox browser only.
    toSource()It is a Non Standard method of the Error object.

  • Custom Events

    Custom Events

    The custom events in JavaScript define and handle custom interactions or signals within an application. They establish a communication mechanism between various sections of your code: one part can notify others about specific occurrences or changes; thus enhancing the functionality of your program.

    Typically, users utilize custom events in conjunction with the Event and CustomEvent interfaces. The following provides a detailed breakdown of their functionality:

    ConceptDescription
    Custom EventThe CustomEvent constructor in JavaScript facilitates communication between various parts of an application by defining a user-specific event. Such custom events manifest as instances of this constructor.
    CustomEvent ConstructorThe built-in JavaScript constructor creates custom events, utilizing two parameters: the event type, a string, and a discretionary configuration object; for instance, an optional detail property can be used to provide supplementary data.
    dispatchEvent MethodA method available on DOM elements that dispatches a custom event. It triggers the execution of all listeners for that event type on the specified element.
    addEventListener MethodA method available on DOM elements to attach an event listener function to an event type. The listener function is executed when the specified event is dispatched on the element.
    Event TypesStrings that identify the type of event. Custom events can have any user-defined string as their type.
    Event HandlingListening for and responding to events is an active process. It primarily involves the creation of listeners for specific event types in custom contexts, and subsequently defining precise actions that will occur when these events take place.
    Pub/Sub PatternIn this design pattern, system components communicate with each other indirectly and without direct references. By utilizing custom events, one can implement a publish/subscribe pattern that enables various application sections to subscribe to specific events and react accordingly.
    detail PropertyAn optional property in the configuration object when creating a custom event. It allows you to pass additional data (as an object) along with the event.

    Example: Basic Custom Event

    In this example, we initiate a custom event named ‘myCustomEvent’ and render an associated button. Using the addEventListener method, we track events triggered by this button. Upon clicking the button, our action dispatches the custom event; subsequently alerting a message “Custom event triggered!”

    <!DOCTYPE html><html><body><button id="triggerBtn">Trigger Event</button><script>// Creates the new custom event.const customEvent =newEvent('myCustomEvent');// Adds an event listener to the button.
    		document.getElementById('triggerBtn').addEventListener('click',function(){// Dispatches custom event on button click.
    			document.dispatchEvent(customEvent);});// Add listener for the custom event.
    		document.addEventListener('myCustomEvent',function(){alert('Custom event triggered!');});</script></body></html>

    Example: Custom Event with Data

    In this example we will make use of the CustomEvent which is an interface and extends the primary Event. The detail property will be demonstrated here which allows us to set additional data. The custom event name will be ‘myCustomEventWithData’ and it will have a message associated to it. This custom event will be getting dispatched upon the click of a button. When this button is clicked, this event will be triggered and the message set will be alerted on screen.

    <!DOCTYPE html><html><body><button id="triggerBtn">Trigger Custom Event</button><script>const eventData ={ message:'Hello from custom event!'};const customEvent =newCustomEvent('myCustomEventWithData',{ detail: eventData });
    		document.getElementById('triggerBtn').addEventListener('click',function(){       
    			document.dispatchEvent(customEvent);});
    		document.addEventListener('myCustomEventWithData',function(event){alert('Custom event triggered with data: '+ event.detail.message);});</script></body></html>

    Example: Condition-based Event Dispatching

    This example illuminates a scenario: event dispatching critically hinges on a variable (v), being conditionally based. It underscores your application’s dynamic use of custom events, dependent upon specific conditions. The case at hand involves the dispatching either ‘TutorialEvent’ or ‘TutorialEvent2’ determined by the value of v; correspondingly, an event listener reacts accordingly to this choice.

    <!DOCTYPE html><html><body><script>var v='tutorialspoint';const event =newEvent("TutorialEvent");const event2 =newEvent("TutorialEvent2");
    	 
    		document.addEventListener('TutorialEvent',()=>{alert("Welcome to Tutorialspoint Event")});
    		document.addEventListener('TutorialEvent2',()=>{alert("Welcome to Event 2")});if(v =='tutorialspoint'){
    			document.dispatchEvent(event);}else{
    			document.dispatchEvent(event2);}</script></body></html>

    To summarize the steps for creating custom events, we first create an event or Custom event, add the listener using the addEventListener (preferably) and then we trigger or dispatch the event using the. dispatchEvent method.

  • Event Capturing

    Event Capturing

    Event capturing in JavaScript is the initial phase in the event propagation model where the event travels from the root of the document tree down to the target element. During this phase, the browser captures the event on the ancestors of the target element before reaching the target itself.

    Event capturing and event bubbling are two phases in the JavaScript event propagation model. In event capturing, the browser captures and triggers events starting from the root of the document hierarchy and moving down to the target element. On the other hand, event bubbling occurs after the event reaches the target element and then bubbles up from the target to the root.

    Capturing is useful for handling events at higher-level ancestors, while bubbling is the default behaviour where events propagate from the target back up the hierarchy. Understanding both phases is crucial for effective event handling and manipulation of the event flow.

    Let us see some important aspects of event capturing.

    AspectDescription
    PhaseEvent capturing is the initial phase in the event propagation model.
    DirectionCapturing occurs in the reverse order of the element hierarchy, from the root of the document tree down to the target element.
    Use CaseUseful when you want to intercept and handle events at a higher-level ancestor before they reach the target element or trigger any bubbling phase handlers.
    RegistrationRegister event listeners for the capturing phase using the third parameter of addEventListener (e.g., element.addEventListener(‘click’, myFunction, true);).
    PropagationAutomatic propagation that precedes the target and bubbling phases. The event flows down the hierarchy, triggering capturing phase handlers on each ancestor.
    Preventing DefaultUse event.preventDefault() during the capturing phase to prevent the default behavior of the event before it reaches the target.
    Stopping PropagationUse event.stopPropagation() in the capturing phase to stop further propagation of the event, preventing it from reaching the target or triggering bubbling phase handlers.

    Example: Basic Event Capturing

    In this example, we have a container div (container) and a button (myButton) inside it. Two capturing phase event listeners are added using addEventListener with the true parameter to enable capturing. When you click the button, both capturing phase log messages (Container clicked and Button clicked) will be displayed. This illustrates the capturing phase as the event travels from the document root down to the target element.

    <!DOCTYPE html><html><body><div id="container"><button id="myButton">Click me!</button></div><div id ="output"></div><script>const output = document.getElementById('output');
    		document.getElementById('container').addEventListener('click',function(event){
    			output.innerHTML +='Capturing phase - Container clicked'+"<br>";},true);
    
    		document.getElementById('myButton').addEventListener('click',function(event){
    			output.innerHTML +='Capturing phase - Button clicked'+"<br>";},true);</script></body></html>

    Example: Preventing Default Behaviour

    In this example, we have a hyperlink (<a>) with an id of “link”. The capturing phase event listener is attached to the link during the capturing phase. When you click the link, the capturing phase log message (Link clicked) will be displayed, and the default behaviour (navigating to a new page) is prevented using event.preventDefault().

    If the. preventDefault() was not used, it would have navigated the page to https://www.tutorialspoint.com.

    <!DOCTYPE html><html><body><a href="https://www.tutorialspoint.com" id="link">Click me to prevent default</a><script>
    		document.getElementById('link').addEventListener('click',function(event){alert('Capturing phase - Link clicked');
    			event.preventDefault();// Prevent the default behavior (e.g., navigating to a new page)},true);</script></body></html>

    Example: Capturing and Stopping Propagation

    In this example, the parent div’s capturing phase event listener actively halts propagation through the use of ‘event.stopPropagation()’. Only upon clicking the button will you see a log message during capture phase (“Parent clicked”) being displayed; however, it does not trigger any further action within child elements’ capturing phases. This indeed showcases an effective method to arrest additional propagation in this particular instance.

    <!DOCTYPE html><html><body><div id="parent"><button id="child">Click me!</button></div><div id ="output"></div><script>const output = document.getElementById('output');
    document.getElementById('parent').addEventListener('click',function(event){
    output.innerHTML +='Capturing phase - Parent clicked'+"<br>";// Stop further propagation to the child element
    event.stopPropagation();},true);
    document.getElementById('child').addEventListener('click',function(event){
    output.innerHTML +='Capturing phase - Child clicked'+"<br>";},true);</script></body></html>
  • Event Bubbling

    Event Bubbling

    Event bubbling is a concept in JavaScript that refers to the order in which events are handled as they propagate through the DOM (Document Object Model) hierarchy. When an event occurs on a particular element, such as a click or a keypress, it can trigger handlers not only on that specific element but also on its ancestors in the DOM tree.

    Event Bubbling Steps

    Here’s a step-by-step explanation of event bubbling −

    Event Triggering

    • An event is triggered on a specific DOM element, like a button being clicked or a key being pressed.
    • This is the starting point of the event propagation.

    Capturing Phase (optional)

    • The event can optionally go through the capturing phase. This phase starts from the root of the DOM tree and moves towards the target element.
    • During this phase, event handlers registered with the addEventListener method using the third parameter true will be executed.

    Target Phase

    • The event reaches the target element, the one on which the event originally occurred.

    Bubbling Phase

    • After the target phase, the event starts to bubble up from the target element towards the root of the DOM tree.
    • During this phase, event handlers registered without the third parameter or with the third parameter set to false will be executed.

    Event Bubbling using 2 Nested DIVs

    In this example of nested <div> elements, event bubbling is evident as the click event on the child <div> propagates up through the DOM hierarchy to trigger the click event listener on the parent <div>. Despite being clicked on the child, both the child and parent event listeners respond to the click event sequentially.

    This behaviour showcases the default event bubbling mechanism in the DOM, where events traverse from the target element up to its ancestors, allowing multiple elements to respond to the same event. In the console, upon clicking the child <div>, the log messages for both the child and parent event listeners are displayed, illustrating the event bubbling process.

    <!DOCTYPE html><html lang="en"><head><style>.parent {
    			width:600px;
    			height:200px;
    			background-color: #eee;
    			position: relative;
    			cursor: pointer;}.child {
    			width:400px;
    			height:100px;
    			background-color: #66c2ff;
    			position: absolute;
    			top:50px;
    			left:50px;}
    		#message {
    			margin-top:10px;
    			font-weight: bold;}</style></head><body><h2>Nested Divs</h2><div class="parent" id="parentDiv"><div class="child" id="childDiv">Click me!</div></div><div id="message"></div><script>let messageElement = document.getElementById('message');
    
    		document.getElementById('parentDiv').addEventListener('click',function(){
    			messageElement.innerHTML+='Parent div clicked<br>';});
    
    		document.getElementById('childDiv').addEventListener('click',function(){
    			messageElement.innerHTML+='Child div clicked<br>';});</script></body></html>

    The grey box is the parent div and blue box is the child div.

    Event Bubbling using 3 Nested Levels

    In this example with three nested levels of <div> elements, event bubbling is demonstrated as a click on the innermost Level 3 <div> triggers successive click event listeners on the parent Level 2 and Level 1 <div> elements. Styled with distinctive background colours, each level visually represents its hierarchy.

    Upon clicking the Level 3 <div>, the event propagates up, invoking event listeners for higher-level elements. Console logs reveal messages indicating the clicked level and its background colour, showcasing the streamlined event bubbling mechanism for handling nested structures in the DOM.

    <!DOCTYPE html><html><head><style>.level1 {
    			background-color: #ff9999;
    			padding:20px;
    			text-align: center;
    			max-width:80%;
    			cursor: pointer;}.level2 {
    			background-color: #99ff99;
    			padding:15px;}.level3 {
    			background-color: #9999ff;
    			padding:10px;
    			cursor: pointer;}
    		#message {
    			margin-top:10px;
    			font-weight: lighter;
    			border:1px solid #ddd;
    			padding:10px;
    			max-width:80%;
    			background-color: #f9f9f9;
    			border-radius:5px;
    			font-family:'Arial', sans-serif;
    			font-size:14px;
    			color: #333;}</style></head><body><div class="level1" id="div1">
    		Level 1<div class="level2" id="div2">
    			Level 2<div class="level3" id="div3">
    
    			Level 3(Click me!)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="message"&gt;&lt;/div&gt;&lt;script&gt;const messageElement = document.getElementById("message");
    document.getElementById('div1').addEventListener("click",function(event){ messageElement.innerHTML +="Clicked on Level 1, Background Color:"+getComputedStyle(event.target).backgroundColor +"<br>";}); document.getElementById('div2').addEventListener("click",function(event){ messageElement.innerHTML +="Clicked on Level 2, Background Color:"+getComputedStyle(event.target).backgroundColor +"<br>";}); document.getElementById('div3').addEventListener('click',function(event){ messageElement.innerHTML +="Clicked on Level 3, Background Color:"+getComputedStyle(event.target).backgroundColor +"<br>";});</script></body></html>
  • Event Delegation

    Event delegation in JavaScript is a technique that allows us to attach a single event listener to a parent element, and then use the event object to determine which child element triggered the event. This way, we can handle multiple events with a single event listener, and avoid adding too many event listeners to the DOM.

    Steps of Event Delegation

    1. Attach a Listener to a Common Ancestor

    Attach a single event listener to a parent element, encapsulating the elements you wish to monitor; this is in lieu of attaching individual event listeners for each element. Use methods such as addEventListener for efficient implementation.

    2. Check the Target Element

    Inspect the event.target property within the event handler to pinpoint the specific element that triggered it in its common ancestor. Common checks involve scrutinizing tagName, classList, or other target element properties.

    3. Perform the Desired Action

    Based on the identified target element and any specified criteria, execute the desired action or functionality. This could involve modifying content, handling a button click, or performing any custom logic associated with the event.

    Event Delegation Examples

    Example: List Item Clicks

    In this example, we employ event delegation to adeptly manage clicks on a dynamically changing list of tutorials. The <ul> element serving as the shared ancestor for all list items has one solitary event listener attached to it.

    Upon clicking a tutorial, an <li> identifies itself as the target via our skilfully crafted event handler; consequently, enabling logging of that particular tutorial’s content in the console. This demonstrates the streamlined and scalable approach of event delegation in managing dynamic lists.

    <!DOCTYPE html><html><head><style>
    
      ul {list-style-type: none; padding:0;}
      li {margin:5px; 
         padding:10px;
         border:1px solid #ccc;
         cursor: pointer; 
         max-width:30%;}&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;ul id="myList"&gt;&lt;li&gt;Tutorial 1&lt;/li&gt;&lt;li&gt;Tutorial 2&lt;/li&gt;&lt;li&gt;Tutorial 3&lt;/li&gt;&lt;li&gt;Tutorial 4&lt;/li&gt;&lt;li&gt;Tutorial 5&lt;/li&gt;&lt;/ul&gt;&lt;div id ="output"&gt;&lt;/div&gt;&lt;script&gt;const output = document.getElementById("output");const myList = document.getElementById("myList")
      myList.addEventListener("click",function(event){if(event.target.tagName ==="LI"){
            output.innerHTML +="Tutorial clicked: "+ 
    event.target.textContent +"<br>";}});</script></body></html>

    Example: Form Control Changes

    Employing event delegation here allows for the monitoring and logging of changes in form control values: the <form> element acts as a common ancestor, while an input event listener captures alterations within input fields. The script confirms by examining the target element within its handler, that events are indeed related to an <input>. The message, consequently, logs the modified input’s name and new value: this action not only showcases event delegation’s adaptability but also its efficiency in managing dynamic form interactions.

    <!DOCTYPE html><html><body><form id="myForm"><input type="text" name="username" placeholder="Username"><input type="password" name="password" placeholder="Password"><button type="button">Submit</button></form><div id="message"></div><script>const messageElement = document.getElementById("message");const myForm = document.getElementById("myForm")
    
      myForm.addEventListener("input",function(event){if(event.target.nodeName ==="INPUT"){
            messageElement.innerHTML +="Input changed: "+ event.target.name +" - New value: "+ event.target.value+'&lt;br&gt;';}});&lt;/script&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Event delegation is valuable in scenarios where a single event listener can efficiently manage interactions for multiple elements, reducing redundancy and improving performance. Common use cases include handling dynamic lists, form interactions, table actions, accordion or tabbed interfaces, tree structures, dropdown menus, multi-step wizards, carousels, and various interactive UI components. It simplifies code structure, ensures consistency, and adapts well to dynamic content changes, making it a versatile technique in web development.

  • Window/Document Events

    JavaScript window events are actions that occur when the user does something affecting the entire browser window, like loading, resizing, closing, or moving the window. The most common window event is simply loading the window by opening a particular web page. This event is handled by the onload event handler.

    Developers can use JavaScript to create dynamic, interactive web pages that respond to user actions. The interactivity depends on two core aspects: window events and document events. Operating at the browser’s panoramic level, window events bestow control over the overall state of the browser window; alternatively, document events interact with the HTML document, empowering developers to react specifically towards elements or actions within a page

    Window Events

    At the browser level, window events happen and hold association with the window object; this global object represents the web browser’s window. Frequently employed to oversee the overall state of a browser window or manage global interactions are these types of events.

    Event NameDescription
    loadTriggered when the entire web page, including all its resources, has finished loading.
    unloadFired when the user is leaving the page or closing the browser window or tab.
    resizeActivated when the size of the browser window is changed.
    scrollFired when the user scrolls the page.

    Example: Demonstrating Window Events

    In this example, a script actively listens for the ‘load,’ ‘resize,’ and ‘scroll’ events on the window; it includes an initial page load alert to inform users that loading is complete. Should they subsequently resize their window, an alert will trigger thereby displaying the new size of their updated viewport. Moreover, when the user scrolls on the page, an alert is triggered to indicate their action.

    <!DOCTYPE html><html><head><title>Window Events Example</title><style>
    
      body {
         height:2000px;/* Adding some content just to enable scrolling */}
      #resizeInfo {
         position: fixed;
         top:10px;
         left:10px;
         background-color: #fff;
         padding:10px;
         border:1px solid #ccc;}&lt;/style&gt;&lt;script&gt;
      window.addEventListener('load',function(){var initialSizeInfo ='Initial window size: '+ window.innerWidth +' x '+ window.innerHeight;
         document.getElementById('resizeInfo').innerText = initialSizeInfo;alert('The page has finished loading!');});
      window.addEventListener('resize',function(){var newSizeInfo ='New window size: '+ window.innerWidth +' x '+ window.innerHeight;
         document.getElementById('resizeInfo').innerText = newSizeInfo;alert("Page has been resized");});
      window.addEventListener('scroll',function(){alert('You have scrolled on this page.');},{once:true});&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;div id="resizeInfo"&gt;Initial window size: ${window.innerWidth} x ${window.innerHeight}&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</pre>

    Document Events

    Document events on the other hand occur at the level of the HTML document within the window and are associated with the document object which represents the HTML document thereby providing an interface to interact with the content of the page.

    Event NameDescription
    DOMContentLoadedTriggered when the HTML document has been completely loaded and parsed, without waiting for external resources like images.
    clickFired when the user clicks on an element.
    submitTriggered when a form is submitted.
    keydown/keyup/keypressThese events are triggered when a key is pressed, released, or both, respectively.
    changeFired when the value of an input element changes, such as with text inputs or dropdowns.

    Example: Demonstrating Document Events

    In this example, we've included a script that listens for the 'DOMContentLoaded,' 'click,' 'submit,' and 'keydown' events on the document. Upon the 'DOMContentLoaded' event, it logs to the console that the DOM content has been fully loaded. Subsequently, clicking an element triggers an alert displaying the tag name of the clicked element. Submitting a form also alerts that the form has been submitted. Furthermore, pressing a key like entering the username with characters, alerts every keypress to the screen.

    <!DOCTYPE html><html><head><title>Document Events Example</title><script>
    
      document.addEventListener('DOMContentLoaded',function(){alert('DOM content has been fully loaded!');});
      document.addEventListener('click',function(event){alert('Element clicked! Tag Name: '+ event.target.tagName);},{once:true});
      document.addEventListener('submit',function(){alert('Form submitted!');});
      document.addEventListener('keydown',function(event){alert('Key pressed: '+ event.key);},{once:true});&lt;/script&gt;&lt;/head&gt;&lt;body&gt;&lt;form&gt;&lt;label for="username"&gt;Username:&lt;/label&gt;&lt;input type="text" id="username" name="username"&gt;&lt;button type="submit"&gt;Submit&lt;/button&gt;&lt;/form&gt;&lt;/body&gt;&lt;/html&gt;</pre>