Closures and executing JavaScript on page load

Share this article

Over on my other blog I’ve just published a new technique for executing a piece of JavaScript once a page has finished loading. Here’s the code:


function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

addLoadEvent(nameOfSomeFunctionToRunOnPageLoad);
addLoadEvent(function() {
  /* more code to run on page load */ 
});

My other post has a run-down of why this technique is needed and an explanation of how it works, but I’d like to expand on that here by talking about the way the above code uses a JavaScript language feature known as a closure.

A closure consists of a function along with the lexical environment (the set of available variables) in which it was defined. This is a remarkably powerful concept, and one commonly seen in functional programming languages such as JavaScript. Here’s a simple example of closures in action:


function createAdder(x) {
  return function(y) {
    return y + x;
  }
}

addThree = createAdder(3);
addFour = createAdder(4);

document.write('10 + 3 is ' + addThree(10) + '
'); document.write('10 + 4 is ' + addFour(10));
createAdder(x) is a function that returns a function. In JavaScript, functions are first-class objects: they can be passed to other functions as arguments and returned from functions as well. In this case, the function returned is itself a function that takes an argument and adds something to it.

Here's the magic: the function returned by createAdder() is a closure. It "remembers" the environment in which it was created. If you pass createAdder the integer 3, you get back a function that will add 3 to its argument. If you pass 4, you get back a function that adds 4. The addThree and addFour functions in the above example are created in this way.

Let's take another look at the addLoadEvent function. It takes as its argument a callback function which you wish to be executed once the page has loaded. There follow two cases: in the first case, window.onload does not already have a function assigned to it, so the function simply assigns the callback to window.onload. The second case is where the closure comes in: window.onload has already had something assigned to it. This previously assigned function is first saved in a variable called oldonload. Then a brand new function is created which first executes oldonload, then executes the new callback function. This new function is assigned to window.onload. Thanks to the magical property of closures, it will "remember" what the initial onload function was. Further more, you can call the addLoadEvent function multiple times with different arguments and it will build up a chain of functions, making sure that everything will be executed when the page loads no matter how many callbacks you have added.

Closures are a very powerful language feature but can take some getting used to. This article on Wikipedia provides more in-depth coverage.

Frequently Asked Questions about JavaScript Closures and Page Load Execution

What is the significance of JavaScript closures in page load execution?

JavaScript closures play a crucial role in page load execution. They allow a function to have “private” variables. The function has access to its own scope, the outer function’s scope, and the global scope. This is particularly useful in asynchronous operations like page load execution where you might need to preserve the state of certain variables across different stages of the page load process.

How does the window.onload event work in JavaScript?

The window.onload event in JavaScript is triggered when the entire webpage, including all its related resources like images and scripts, have finished loading. This event is often used to execute scripts that require the entire DOM and all its related resources to be fully loaded before they can run correctly.

How can I ensure my JavaScript code runs after the page has fully loaded?

You can ensure your JavaScript code runs after the page has fully loaded by placing your code inside a function and then attaching that function to the window.onload event. This will ensure that your code only runs once the entire webpage and all its related resources have finished loading.

What is the difference between window.onload and document.onload?

The main difference between window.onload and document.onload is when they are triggered. The document.onload event is triggered when the HTML document has been completely loaded and parsed, but without waiting for stylesheets, images, and subframes to finish loading. On the other hand, the window.onload event is triggered when the entire webpage, including all its related resources like images and scripts, have finished loading.

How can I use JavaScript closures to manage state during page load execution?

JavaScript closures can be used to manage state during page load execution by preserving the value of certain variables across different stages of the page load process. This is particularly useful in asynchronous operations where the order of execution might not be linear.

Can I use multiple window.onload events in a single webpage?

Yes, you can use multiple window.onload events in a single webpage. However, it’s important to note that only the last window.onload event will be executed, as each new window.onload event overwrites the previous one. To avoid this, you can use the addEventListener method to attach multiple load events to the window object.

How can I execute a function when a specific element has loaded, instead of waiting for the entire page to load?

You can execute a function when a specific element has loaded by using the onload attribute in the HTML tag of that element. This attribute can be used with tags like img, body, frame, iframe, script, and link.

What is the role of the DOMContentLoaded event in page load execution?

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. This event can be used to execute scripts that only require the DOM to be fully loaded, without needing all the related resources to be loaded.

How can I use JavaScript closures to create private variables?

JavaScript closures can be used to create private variables by defining those variables within a function. These variables are only accessible within that function, effectively making them private.

Can I use the jQuery $(document).ready() function instead of the window.onload event?

Yes, you can use the jQuery $(document).ready() function instead of the window.onload event. This function is triggered when the DOM is ready, which usually happens before the window.onload event. However, it’s important to note that this function requires jQuery to be loaded, and it won’t work if jQuery is not available.

Simon WillisonSimon Willison
View Author
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week