Lazy Object Initialization

By  on  

The Firefox DevTools underlying code, which is written with JavaScript and HTML, is a complex application. Due to the complexity and amount of work going on, the DevTools team has done everything they can to load as little as possible. Furthermore the team has a system of lazily importing and initializing objects when they're needed. I've taken a bit of time to reduce the initializer, let's take a look!

The system relies on taking advantage of Object.defineProperty's get function to initialize an object when needed:

// Lazily initializes an object's property until it's used
function lazyGet(hostObj, name, initializer) {
    let defined = false;
    Object.defineProperty(hostObj, name, {
        get: function () {
            // If not already defined, define it by executing
            // its initializer and setting it as value
            if (!defined) {
                defined = true;
                // Overrides the original property definition
                // which is the initializer
                Object.defineProperty(hostObj, name, {
                    configurable: true,
                    enumerable: true,
                    value: initializer.apply(hostObj),
                    writable: true,
                });
                return hostObj[name];
            }
        },
        configurable: true,
        enumerable: true
    });
}

With the lazyGet function, the property you want is only initialized and processing down when its getter is called:

// Don't define window.myProp until someone tries to use it
// Thus, if it's never used, it's never initialized
lazyGet(window, "myProp", () => {
    return { message: "Hello!" };
});

// window.myProp is now undefined, since it hasn't been requested yet

// Use it for something, which triggers initialization and returns its value
console.log(window.myProp.message);

// Using it again doesn't initialize again, since it was already created
console.log(window.myProp.message);

// And it can be reassigned later on:
window.myProp = null;

Mozilla's initializer is much more complex as it also acts as a loader, but you get the idea. We always think about lazy loading resources but it's also good to think about initializing properties as they may not be needed! Keep a tiny footprint if you can!

Recent Features

  • By
    9 More Mind-Blowing WebGL Demos

    With Firefox OS, asm.js, and the push for browser performance improvements, canvas and WebGL technologies are opening a world of possibilities.  I featured 9 Mind-Blowing Canvas Demos and then took it up a level with 9 Mind-Blowing WebGL Demos, but I want to outdo...

  • By
    Create a CSS Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

Incredible Demos

  • By
    Create a 3D Panorama Image with A-Frame

    In the five years I've been at Mozilla I've seen some awesome projects.  Some of them very popular, some of them very niche, but none of them has inspired me the way the MozVR team's work with WebVR and A-Frame project have. A-Frame is a community project...

  • By
    Animated AJAX Record Deletion Using Dojo

    I'm a huge fan of WordPress' method of individual article deletion. You click the delete link, the menu item animates red, and the item disappears. Here's how to achieve that functionality with Dojo JavaScript. The PHP - Content & Header The following snippet goes at the...

Discussion

  1. This is a nice idea. I think a better example to demonstrate lazy initialization might be:

      return new Date();
    

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!