I was chatting to a mate of mine over the weekend, and he touched on the use of Proxy object in some code he had been working with. I pointed him to my favourite use of a Proxy, which exists in poof (My secure one time secret sharing service), and is useful in any VanillaJS scenario.
The code is on Github but is short enough to add here:
// getElementById helper
// basically you can dereference elements by id.
export const dom = new Proxy(
{},
{
get: (target, prop) => {
if (typeof prop !== "string") {
return target[prop];
}
const id = prop.replace(/^\$/, ""); // allow dom.$id
return document.getElementById(id);
},
}
);
In vanillajs code you often query and cache DOM elements by id
, so that you can attach event handlers or read values from inputs, etc… This (in my code) usually leads to a big block of code like this:
<form id="form">
<input id="input" />
<button id="button">Click</button>
</form>
<script>
const $form = document.getElementById("form");
const $input = document.getElementById("input");
const $button = document.getElementById("button");
// $form.onsubmit = ... etc...
</script>
But with the awesome DOM helper the script part can change to:
const { $form, $input, $button } = dom;
Isn’t that beautiful. The idea could be extended with querySelector
and querySelectorAll
functionality - say a proxy called qs
/ qsa
, so you could dereference with a new variable name like:
const { ["div.foo ul > li"]: $list } = qsa;
This wouldn’t be hard to build, in fact it would be almost the same (simpler even):
const qs = new Proxy(
{},
{
get: (target, prop) => {
if (typeof prop !== "string") {
return target[prop];
}
return document.querySelector(prop);
},
}
);
I have half a mind to make a tiny library out of this, but even without that please copy/paste or just steal the idea!
Edit: I just realised that we can wrap this idea as the form for the two Proxies are almost identical.
function makeProxy(fn) {
return new Proxy({}, {
get: (t, p) => typeof p !== "string" ? t[p] : fn(p);
});
}
const dom = makeProxy(id => document.getElementById(id.replace(/^\$/, "")));
const qs = makeProxy(sel => window.querySelector(sel));
const qsa = makeProxy(sel => window.querySelectorAll(sel));