Darien Valentine (2017-09-11T08:29:28.000Z)
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.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170911/6246d84a/attachment-0001.html>
valentinium at gmail.com (2017-09-11T08:31:56.340Z)
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;

    foo.hasOwnProperty('bar'); // false
    foo.bar;
    foo.hasOwnProperty('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.)