Memoization with Lazy Getters

snippet

TIL JavaScript getters can simply be deleted, even if there’s no corresponding setter:

let obj = {
    data: 123,
    get hash() {
        return this.data * Math.random();
    }
};

obj.hash = 666; // đź’Ą TypeError: setting getter-only property "hash"

delete obj.hash;
obj.hash = 888; // âś…

We can use this to avoid redundant computations, replacing our getter with the respective value upon first invocation:

let obj = {
    data: 123,
    get hash() {
        let value = this.data * Math.random();
        delete this.hash;
        this.hash = value;
        return value;
    }
};

We could alternatively employ Object.defineProperty to the same effect:

let obj = {
    data: 123,
    get hash() {
        let value = this.data * Math.random();
        Object.defineProperty(this, "hash", {
            value,
            writable: false
        });
        return value;
    }
};

This might be preferable because it doesn’t (temporarily) change our object’s shape; delete can trip up engines’ performance optimizations – though I haven’t researched this particular scenario.