Lazy evaluation

Darien Valentine valentinium at gmail.com
Mon Sep 11 09:23:09 UTC 2017


I’m not sure what was sneaky haha ... it was in response to the prior
discussion of that subject, and I think it is quite related to lazy props,
example code aside, since lazy props are just a specific case for the more
general pattern of properties with some form of associated state / stateful
behavior.

The benchmark is great info. I agree that the observability via
hasOwnProperty/getOwnPropertyDescriptor is not at all likely to create
issues for any given case, but I was speaking about my reservations with
library code in mind. For apps or internal classes I simply use
_underscoreProps for the same need. Perhaps property definition is still
faster even then, in which case I’d switch to it for those cases. But for
the public API of a lib, I prefer to stick with the keep-it-unobservable
rule (people have relied on stranger things).

On Mon, Sep 11, 2017 at 4:54 AM, Andrea Giammarchi <
andrea.giammarchi at gmail.com> wrote:

> 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/d33e1ebd/attachment-0001.html>


More information about the es-discuss mailing list