Lazy evaluation

Andrea Giammarchi andrea.giammarchi at gmail.com
Mon Sep 11 08:54:44 UTC 2017


Darien you managed to sneak-in another pattern that has nothing to do with
laziness, it's rather an approach to simulate private variables (exposing
them though).

To meaningfully compare your solution with mine you need these two classes:

```js
const WM = new WeakMap();

class CaseWM {
  get bar() {
    var shadow = WM.get(this);
    if (!shadow) {
      shadow = {bar: Math.random()};
      WM.set(this, shadow);
    }
    return shadow.bar;
  }
}

class CaseLazy {
  get bar() {
    var value = Math.random();
    Object.defineProperty(this, 'bar', {value});
    return value;
  }
}
```

You can verify the benchmark here: https://jsperf.com/lazy-property-patterns

In my Chromium the lazy property is around 4X faster and there's no
GC/memory pressure due WeakMap.

It's a matter of trades-off and compromise. I don't care about
`hasOwnProperty` for properties defined in the prototype, it's a misleading
check anyway and I don't see any real-world side effect, or better, I
cannot think of a single case I've had so far that would've been
problematic.

I use the `in` operator and you should probably do the same if that's a
concern, or maybe explain why/when/how that could be a concern.

Regards




On Mon, Sep 11, 2017 at 9:29 AM, Darien Valentine <valentinium at gmail.com>
wrote:

> I use the WeakMap approach, too. Recently I find myself writing classes
> where the class has a corresponding WeakMap holding the "shadow instances"
> (as opposed to having one WM per property):
>
>     const PRIV = new WeakMap();
>
>     class Foo {
>       constructor() {
>         PRIV.set(this, { bar: 0, /*...other private state init...*/ });
>       }
>
>       get bar() {
>         return PRIV.get(this).bar;
>       }
>
>       set bar(val) {
>         if (!Number.isInteger(val)) throw new TypeError('no!');
>
>         PRIV.get(this).bar = val;
>       }
>     }
>
> I only do this for classes that are part of some public interface, where I
> want finer control over what state is exposed and wish to ensure that the
> object cannot enter an invalid state; for internal stuff it’d probably be
> overkill.
>
> The property-that-redefines-itself approach makes me uncomfortable because
> I don’t want property access to have observable side effects from the
> consumer side.
>
>     const foo = new ClassWithThatPattern;
>
>     Object.hasOwnProperty(foo, 'bar'); // false
>     foo.bar;
>     Object.hasOwnProperty(foo, 'bar'); // true
>
> In any case ... re: lazy initialization, I would agree that decorators
> represent a perfect way to make this pattern declarative & expressive. I
> suppose the private instance properties aspect of the class properties
> proposal, now at stage 3, also provides a way to reduce boilerplate by a
> bit, but not to the same degree.
>
> (I’d second kaizu’s opinion that the example of lazy init of a db seems
> kind of iffy, at least for node apps, where you kinda want to know your db
> is working before you even init the rest of the app, as failure almost
> invariably represents a terminal condition — but that said, it’s just an
> example, and there are certainly cases where lazy init of properties is
> worthwhile, e.g. when you have very large collections of many small
> instances and only an unknown-in-advance subset will actually need
> such-and-such properties calculated ultimately.)
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170911/74b25850/attachment.html>


More information about the es-discuss mailing list