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
    Regular Expressions for the Rest of Us

    Sooner or later you'll run across a regular expression. With their cryptic syntax, confusing documentation and massive learning curve, most developers settle for copying and pasting them from StackOverflow and hoping they work. But what if you could decode regular expressions and harness their power? In...

  • By
    Conquering Impostor Syndrome

    Two years ago I documented my struggles with Imposter Syndrome and the response was immense.  I received messages of support and commiseration from new web developers, veteran engineers, and even persons of all experience levels in other professions.  I've even caught myself reading the post...

Incredible Demos

  • By
    jQuery Random Link Color Animations

    We all know that we can set a link's :hover color, but what if we want to add a bit more dynamism and flair? jQuery allows you to not only animate to a specified color, but also allows you to animate to a random color. The...

  • By
    MooTools, Mario, and Portal

    I'm a big fan of video games. I don't get much time to play them but I'll put down the MacBook Pro long enough to get a few games in. One of my favorites is Portal. For those who don't know, what's...

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!