JavaScript Getter Factory ~ Properties from thin air ~

Adam Crockett 🌀 - May 10 '23 - - Dev Community

Ive been looking back at one of my favourite library creations, which I still use in my projects and have a whole methodology around it, Reactive CSS Properties, but I want to talk today about a technical aspect of the library which I find very interesting, a little magic but still very cool and imperative.

const BLANK = {};
const getterFactory = new Proxy(BLANK, {
    get(tar, prop, value) {
        // no matter what return an object
        return {
            imANewThing: 'woo!'
        }
    }
});

export { getterFactory }; 
Enter fullscreen mode Exit fullscreen mode

What we have here is a blank object that ideally you would not reference so it isn't accessible, its just a placeholder, when you access a property like this

import { getterFactory } from 'thinAir';
getterFactory.foo
// or
const { justAboutAnythingYouWant } = getterFactory;
Enter fullscreen mode Exit fullscreen mode

You will always give you a new instance of an object with imANewThing. Thats quite cool if for example you want to conveniently create something in a library. for example in my reactive css properties library:

import rCSSProps from "reactive-css-properties";

// rCSSProps object has no undefined properties and will always yield a class-like callable object.
// The name of your destructured variable is the name of the css variable in snake-case
const { themeTextColor } = rCSSProps();

// insert `--theme-text-color: #000;` into the root element `style` (<html> in this example).
themeTextColor("#000");

// or provide a fallback for browsers which do not support css custom properties
themeTextColor("#000", "#000");
Enter fullscreen mode Exit fullscreen mode

I was just destructuring css custom properties out of nowhere, the rCSSProps is our getter factory and it is a function which can then configure the output of all of the getters.

nice huh?

Well I hope you like the idea and maybe you can think of a sweet web server using something like:

const { homeRoute, someOtherRoute, byeBye } = route('/foo');

homeRoute.get = () => {

}


byeBye;
Enter fullscreen mode Exit fullscreen mode

ps, for the geeks like me, how is this working?

Simple, in any attempt to get any property on our object through ['squareBrackets'], .dotNotaiton or { destructure } we divert the usual return value of the get in the proxy get trap handler thing, and disregard the usual undefined in favour of a value we control.
In a way its like a class in that we instantiate it by proxy, but its actually no different to a regular variable reference.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .