Destructuring instances with private fields

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Destructuring instances with private fields

kdex
Often times, when I use a class field a lot, I create a local binding for it,
so that I don't have to prefix every appearance with `this.`:

```js
class Foo {
        bar = 1;
        method() {
                const { bar } = this;
                /* … */
        }
}
```

The same approach would currently be illegal syntax if `bar` is declared to be
private:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar } = this;
                /* … */
        }
}
```

How is the destructuring assignment supposed to behave anyway? Introduce a
local `bar` binding, just like above?

Whatever it should do, even defining an explicit name for the binding is
currently illegal:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar: bar } = this;
                /* … */
        }
}
```

This feels really asymmetric to public fields and has come up in the class
fields proposal[1] before, though it was suggested to defer it to a separate
proposal.

Is someone currently working on said proposal?

[1] https://github.com/tc39/proposal-class-fields/issues/4
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Destructuring instances with private fields

Ranando King
I can understand why this would be wanted. It would save some excess typing. However, doesn't it also lead to the potential foot-gun of forgetting to assign any modifications back to the original private field? Also, since private fields aren't actually own properties of the instance, how could they possibly be destructured? There's no programmatically exposed listing of the private fields. Further, under proposal-class-fields private fields are restricted to just `class` instances, so the destructuring syntax doesn't make sense for that scenario. Basically it would imply that the following is true:

```js
let bar1 = "bar", bar2;
({ #fubar: bar2}) = { #fubar: bar1 };
bar1 === bar2;
```

Even if proposal-class-fields allowed for private fields on objects, it wouldn't work. There's no way to reify the left side's `#fubar` as a private name of the object on the right side before processing the object on the right side. Put another way, without `obj.` in front of it, `#field` cannot be lexically resolved as a private name while parsing unless the parser, upon finding the object on the right side of the `=`, re-evaluates the left side. Since destructuring can be arbitrarily complex, this becomes a mess very nearly as complex as trying to accurately deep clone an arbitrary object.

On Wed, Sep 5, 2018 at 3:12 PM kdex <[hidden email]> wrote:
Often times, when I use a class field a lot, I create a local binding for it,
so that I don't have to prefix every appearance with `this.`:

```js
class Foo {
        bar = 1;
        method() {
                const { bar } = this;
                /* … */
        }
}
```

The same approach would currently be illegal syntax if `bar` is declared to be
private:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar } = this;
                /* … */
        }
}
```

How is the destructuring assignment supposed to behave anyway? Introduce a
local `bar` binding, just like above?

Whatever it should do, even defining an explicit name for the binding is
currently illegal:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar: bar } = this;
                /* … */
        }
}
```

This feels really asymmetric to public fields and has come up in the class
fields proposal[1] before, though it was suggested to defer it to a separate
proposal.

Is someone currently working on said proposal?

[1] https://github.com/tc39/proposal-class-fields/issues/4_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Destructuring instances with private fields

Isiah Meadows-2
BTW, this just falls out of the grid with my private symbols suggestion....
https://github.com/tc39/proposal-class-fields/issues/115

On Thu, Sep 6, 2018 at 10:14 Ranando King <[hidden email]> wrote:
I can understand why this would be wanted. It would save some excess typing. However, doesn't it also lead to the potential foot-gun of forgetting to assign any modifications back to the original private field? Also, since private fields aren't actually own properties of the instance, how could they possibly be destructured? There's no programmatically exposed listing of the private fields. Further, under proposal-class-fields private fields are restricted to just `class` instances, so the destructuring syntax doesn't make sense for that scenario. Basically it would imply that the following is true:

```js
let bar1 = "bar", bar2;
({ #fubar: bar2}) = { #fubar: bar1 };
bar1 === bar2;
```

Even if proposal-class-fields allowed for private fields on objects, it wouldn't work. There's no way to reify the left side's `#fubar` as a private name of the object on the right side before processing the object on the right side. Put another way, without `obj.` in front of it, `#field` cannot be lexically resolved as a private name while parsing unless the parser, upon finding the object on the right side of the `=`, re-evaluates the left side. Since destructuring can be arbitrarily complex, this becomes a mess very nearly as complex as trying to accurately deep clone an arbitrary object.

On Wed, Sep 5, 2018 at 3:12 PM kdex <[hidden email]> wrote:
Often times, when I use a class field a lot, I create a local binding for it,
so that I don't have to prefix every appearance with `this.`:

```js
class Foo {
        bar = 1;
        method() {
                const { bar } = this;
                /* … */
        }
}
```

The same approach would currently be illegal syntax if `bar` is declared to be
private:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar } = this;
                /* … */
        }
}
```

How is the destructuring assignment supposed to behave anyway? Introduce a
local `bar` binding, just like above?

Whatever it should do, even defining an explicit name for the binding is
currently illegal:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar: bar } = this;
                /* … */
        }
}
```

This feels really asymmetric to public fields and has come up in the class
fields proposal[1] before, though it was suggested to defer it to a separate
proposal.

Is someone currently working on said proposal?

[1] https://github.com/tc39/proposal-class-fields/issues/4_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Destructuring instances with private fields

Ranando King
I can make it work work under my proposal-object-members by making '#' a postfix unary operator, but then it would have to be a syntax error to use it that way unless we're dealing with a destructuring operation. That just opens up too many ways to abuse it and leak the private container. So that's a no-go as well.

On Thu, Sep 6, 2018 at 10:45 AM Isiah Meadows <[hidden email]> wrote:
BTW, this just falls out of the grid with my private symbols suggestion....
https://github.com/tc39/proposal-class-fields/issues/115

On Thu, Sep 6, 2018 at 10:14 Ranando King <[hidden email]> wrote:
I can understand why this would be wanted. It would save some excess typing. However, doesn't it also lead to the potential foot-gun of forgetting to assign any modifications back to the original private field? Also, since private fields aren't actually own properties of the instance, how could they possibly be destructured? There's no programmatically exposed listing of the private fields. Further, under proposal-class-fields private fields are restricted to just `class` instances, so the destructuring syntax doesn't make sense for that scenario. Basically it would imply that the following is true:

```js
let bar1 = "bar", bar2;
({ #fubar: bar2}) = { #fubar: bar1 };
bar1 === bar2;
```

Even if proposal-class-fields allowed for private fields on objects, it wouldn't work. There's no way to reify the left side's `#fubar` as a private name of the object on the right side before processing the object on the right side. Put another way, without `obj.` in front of it, `#field` cannot be lexically resolved as a private name while parsing unless the parser, upon finding the object on the right side of the `=`, re-evaluates the left side. Since destructuring can be arbitrarily complex, this becomes a mess very nearly as complex as trying to accurately deep clone an arbitrary object.

On Wed, Sep 5, 2018 at 3:12 PM kdex <[hidden email]> wrote:
Often times, when I use a class field a lot, I create a local binding for it,
so that I don't have to prefix every appearance with `this.`:

```js
class Foo {
        bar = 1;
        method() {
                const { bar } = this;
                /* … */
        }
}
```

The same approach would currently be illegal syntax if `bar` is declared to be
private:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar } = this;
                /* … */
        }
}
```

How is the destructuring assignment supposed to behave anyway? Introduce a
local `bar` binding, just like above?

Whatever it should do, even defining an explicit name for the binding is
currently illegal:

```js
class Foo {
        #bar = 1;
        method() {
                const { #bar: bar } = this;
                /* … */
        }
}
```

This feels really asymmetric to public fields and has come up in the class
fields proposal[1] before, though it was suggested to defer it to a separate
proposal.

Is someone currently working on said proposal?

[1] https://github.com/tc39/proposal-class-fields/issues/4_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss