DEV Community

Adam Crockett 🌀
Adam Crockett 🌀

Posted on

🦓 How I created an Infinite object with no undefined properties!? (revised)

😅 What if... just by observing light we can see either a wave or a particle, oh we can? Okay, well what if by getting the property of an object, we cause that property to spring into being?

A long time ago I wondered, why can't JavaScript objects dot notate properties that don't exist? Well I suppose it's a little error prone to mis-spell a property name and have it get some data anyway, but actually you don't always know what your property name is going to be and at any depth, you can already set names for properties without much thought.. it's no more error prone than that.

So I set to work, when an object is wrapped in a proxy, and the proxy attempts to get, define the name of the requested property onto the target object as another object and if that property does not exist.. recursively set the new object as a proxy also and that's it... Endless objects

It's been a few years since I wrote the original but today I have revised the code to add some best practices. Although at this point it might as well be magic which to me isn't best practice 😜.

const infinieSet = (obj) => {
    return new Proxy(obj, {
        get(tar, prop){
            if(!Object.prototype.hasOwnProperty.call(tar, prop)){
                tar[prop] = {};
            }
            return infinieSet(tar[prop]);
        },
    })
}
Enter fullscreen mode Exit fullscreen mode

Usage:

const infinite = infinieSet(target);

// pointless destructure works XD
const {some: {obj: {magic}}} = infinieSet(target);
console.log(magic); // {}

// or

infinite.this.is.not.defined = 'ummm'
infinite.and.yet.it.is = 'huh?'
infinite.the.potential.is.endless ='what is it for?'
infinite
    .template
    .locals
    .could
    .be
    .easier
    .to
    .extend
    .if
    .you
    .could
    .just
    .do
    .this = 'but it must have a value'

// or even from a string
eval('infinite.x.y.z');

/*
{
    "some": {
        "obj": {
            "magic": {}
        }
    },
    "this": {
        "is": {
            "not": {
                "defined": "ummm"
            }
        }
    },
    "and": {
        "yet": {
            "it": {
                "is": "huh?"
            }
        }
    },
    "the": {
        "potential": {
            "is": {
                "endless": "what is it for?"
            }
        }
    },
    "template": {
        "locals": {
            "could": {
                "be": {
                    "easier": {
                        "to": {
                            "extend": {
                                "if": {
                                    "you": {
                                        "could": {
                                            "just": {
                                                "do": {
                                                    "this": "but it must have a value"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "x": {
        "y": {
            "z": {}
        }
    }
}
*/
Enter fullscreen mode Exit fullscreen mode

Okay so what is going on here?

Using meta programming, I have allowed undefined props for this object to be accessed (created on demand) as if they already had a value, I have used a recursive proxy technique, it looks a bit like the prototype chain the key difference is that I can control the output of what is defined on the fly.

Why did I do this?

Because I was showing off, but it turns out this has been useful over the years, Simply put, this is way more efficient (nicer to create deep objects such as filesystems). I said at the time:

I am building an api in express, I don't want to return undefined or cause template errors that crash the page, instead I want to give the option on a special locals object to dynamically assign props to the api and if not defined (although they are), show useful errors as a reaction rather than a catch.

Top comments (0)