Lazy Object Initialization
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!
This is a nice idea. I think a better example to demonstrate lazy initialization might be: