How to Call a JavaScript Function in HTML

Everything you need to know about calling JavaScript functions in an HTML document—incl. placement, async/defer, and sync.

Published Categorized as JavaScript

In JavaScript, you can declare and call functions.

Declaring a function loads it into the device’s memory, so that its code can be executed later.

The following is a declaration of a function that returns the string “Hello, world!” whenever it’s executed:

function sayHello(){
  return "Hello, world!";
}

Calling a function, on the other hand, is what triggers the execution of that code and gets the function to return a result.

And here’s how we can call the function:

sayHello();

If you’re building a website, you will need to call your JavaScript functions within the HTML documents that it consists of.

There are several ways to call a JavaScript function in an HTML document. In this tutorial, I will guide you through each of them, so you can choose the one that suits your needs best.

Calling a JavaScript Function in HTML

Generally speaking, you can call a JavaScript function in either the <head> or the <body> section of your HTML document.

The placement of your JavaScript function calls can affect when the function is executed, as well as how quickly the rest of your web page loads.

Calling a JavaScript Function in the <head>

<!doctype html>
<html class="no-js" lang="">

<!-- The <head> section of your HTML document -->
<head>
  <script>
    // Declare  the JavaScript function
    function sayHello(){
      return "Hello, world!";
    }
    
    // Call the JavaScript function
    sayHello();
  </script>
</head>

<!-- The <body> section of your HTML document -->
<body>
  <h1>Sample Heading</h1>
</body>

If you call a function in the <head> section of your HTML document, it will execute as soon as the browser comes across the function call as it parses the HTML file.

This may cause issues if the function relies on HTML elements, or the DOM (Document Object Model), that haven’t been loaded yet. For example, if you try to access an HTML element that appears later in the <body>, it may not exist at the time the function executes in the <head>, which would trigger an error.

Specifically, if you tried to do this:

<!doctype html>
<html class="no-js" lang="">

<!-- The <head> section of your HTML document -->
<head>
  <script>
    // Declare function to say "Hello, world!"
    function sayHello() {
      return "Hello, world!";
    }

    // Declare function to overwrite <h1> with the return value of sayHello();
    function setText() {
      var heading = document.querySelector("h1"); // Select the <h1> element
      heading.textContent = sayHello(); // Set its content to the return value of the function
    }

    // Call the function to overwrite the text
    setText();
  </script>
</head>

<!-- The <body> section of your HTML document -->
<body>
  <h1>Sample Heading</h1>
</body>

</html>

It would trigger a Uncaught TypeError: Cannot set properties of null (setting 'textContent') error in the browser console because you are calling a function that modifies an HTML element before that element has appeared in the DOM tree.

To make it work, you would need to call the JavaScript function in the HTML document’s <body> section, either immediately after the <h1> element or right before the closing of the </body> tag.

Calling a JavaScript Function in the <body>

<!doctype html>
<html class="no-js" lang="">

<!-- The <head> section of your HTML document -->
<head>
  <script>
    // Declare function to say "Hello, world!"
    function sayHello() {
      return "Hello, world!";
    }

    // Declare function to overwrite <h1> with the return value of sayHello();
    function setText() {
      var heading = document.querySelector("h1"); // Select the <h1> element
      heading.textContent = sayHello(); // Set its content to the return value of the function
    }
  </script>
</head>

<!-- The <body> section of your HTML document -->
<body>
  <h1>Sample Heading</h1>
  <!-- Calling a function in the HTML document's footer -->
  <script>
    // Call the function to overwrite the text
    setText();
  </script>
</body>

</html>

Placing function calls in the <body> section is a common practice, especially near the end of the <body> or when using event handlers.

When the function call is encountered in the <body>, it executes at that point, oftentimes after the entire HTML content and DOM have been loaded.

By placing function calls in the <body>, you ensure that all necessary HTML elements are present and accessible when the functions need to run. This helps to prevent errors related to accessing undefined elements.

When to Call in the <head>, And When in the <body>

Call JavaScript functions in the <head> section of an HTML document when they:

  1. Don’t need to parse or manipulate HTML elements in the DOM tree;
  2. Must be executed, whether asynchronously or synchronously, as soon as the user has opened the web page.

Common examples for JavaScript functions that need to be called in the <head> section of an HTML document include the code snippets for client-side tagging and analytics tools Google Tag Manager, Google Analytics, or Microsoft Clarity.

Call JavaScript functions in the <body> section of an HTML document when they:

  1. Need to parse and/or manipulate HTML elements in the DOM tree;
  2. Can be executed after the entire DOM tree, or a part of it, has already loaded.

Examples include functions that need to append URL parameters to hyperlinks in <a> elements or add/change text or multimedia in the DOM using JavaScript.

How Your Call Placement Impacts Performance

When you dig deeper into how JavaScript works, it’s important to understand the concepts of render-blocking and non-render-blocking functions.

In web development, “render-blocking” refers to things that slow down or delay the display of a web page, while non-render-blocking functions don’t affect how the page is shown.

This difference is really important because it has a big impact on how fast your website loads and performs.

Render-blocking JavaScript

Render-blocking is often associated with JavaScript code, and more specifically, the placement of the script.

Scripts placed in the <head> of your HTML document are typically considered render-blocking, as the browser pauses the parsing of HTML to fetch and execute these scripts.

During this pause, the user sees a blank page, which can negatively impact user experience, particularly for users with slower network connections.

Going back to our previous examples, when we place the sayHello function in the <head> of our HTML document:

<!-- The <head> section of your HTML document -->
<head>
  <script>
    // Declare  the JavaScript function
    function sayHello(){
      return "Hello, world!";
    }
    
    // Call the JavaScript function
    sayHello();
  </script>
</head>

This script is considered render-blocking.

The browser has to stop parsing the HTML, fetch the script, execute it, and only then can it continue to render the page.

This delay is generally negligible for small scripts, but for larger or numerous scripts, the delay becomes increasingly noticeable.

Non-render-blocking JavaScript

In contrast, non-render-blocking scripts don’t interrupt the parsing of HTML.

The browser can continue rendering the webpage while concurrently downloading the script, resulting in a quicker and more seamless user experience.

This is typically achieved by placing scripts right before the closing </body> tag, as shown in our setText function example:

<!-- The <body> section of your HTML document -->
<body>
  <h1>Sample Heading</h1>
  <!-- Calling a function in the HTML document's footer -->
  <script>
    // Call the function to overwrite the text
    setText();
  </script>
</body>

This script is non-render-blocking because it doesn’t interfere with the initial page render. It executes after the HTML parsing is nearly finished, ensuring the entire DOM tree is available for any needed manipulations.

It significantly improves the perceived load time for users. (I’m using the word “perceived” because, technically, the page takes as long to load as it did before; it’s just that its DOM is painted before the JavaScript function is executed.)

Alternatively, we can make scripts non-render-blocking by using the async or defer attributes.

Synchronous vs. Asynchronous Execution

Now that we know about the implications of script placement and its impact on render-blocking, we can get into synchronous and asynchronous execution modes in JavaScript.

In synchronous execution, JavaScript runs line by line, from top to bottom.

It means that JavaScript will execute one operation at a time, in the order that they appear. If a function takes a long time to execute (like fetching data from a server), it will block or halt the execution of the subsequent functions until it finishes.

This mode of operation might lead to an undesirable “freeze” in your website, as I’m sure you’ve come across in your daily browsing.

On the other hand, asynchronous execution allows JavaScript to start a function, move on to the next, and then come back when the result of the function is ready.

Async is especially useful for actions that depend on external factors like server requests, timers, or user interactions. Asynchronous execution ensures that these activities don’t block the flow of your code.

// Synchronous example
console.log('First');
console.log('Second'); // This won't run until the first console.log has finished

// Asynchronous example
console.log('First');
setTimeout(function() { console.log('Second'); }, 0); // This will run in the background
console.log('Third'); // This will run without waiting for the setTimeout function

In the asynchronous example, JavaScript does not wait for the setTimeout function to complete before moving on to console.log('Third');.

Instead, it starts the timer and continues executing the next lines of code. When the timer finishes, it comes back and executes the code inside setTimeout.

Remember, balancing render-blocking functions, asynchronous calls, and the overall structure of your JavaScript code is key to building a fast, efficient, and user-friendly website.

By Dim Nikov

Editor of Maker's Aid. Part programmer, part marketer. Making things on the web and helping others do the same since the 2000s. Yes, I had Friendster and Myspace.

Leave a comment

Your email address will not be published. Required fields are marked *