I also agree private properties / instance variables should not be class-exclusive.
I was a big fan of the syntax used in the JavaScript Classes 1.1 proposal ( https://github.com/zenparsing/js-classes-1.1#1-instance-variables) and always felt like it could have been painlessly extended to plain old objects. On Fri, Aug 3, 2018 at 11:30 PM, Bob Myers <[email protected]> wrote: > > `private`, `protected`, `class`, and a few other such keywords have all > been part of ES since long be for the TC39 board got their hands on it. > They hadn't been implemented, but they were all a very real part of ES. > > Whoa. Is that just misinformed or intentionally misleading? They have > never been "part of ES" in any meaningful sense. It was not that they had > not been implemented; it was that they had not even been defined. To say > they are a "real part of ES" is a strange interpretation of the meaning of > the word "real". The notion that we would choose features to work on based > on some designation of certain keywords as reserved long ago, and that they > are now "languishing", is odd. Why not focus on "implementing" enum, or > final, or throws, or any other of the dozens of reserved words? > > Having said that, I think it is a valid general principle that as language > designers we should be very reluctant to use magic characters. `**` is > fine, of course, as is `=>`, or even `@` for decorators. Personally, I > don't think the problem of access modifiers rises to the level of > commonality and need for conciseness that would justify eating up another > magic character. We also don't want JS to start looking like Perl or APL. > > Speaking as a self-appointed representative of Plain Old Programmers, I do > feel a need for private fields, although it was probably starting to > program more in TS that got me thinking that way. However, to me it feels > odd to tie this directly to `class` syntax. Why can't I have a private > field in a plain old object like `{a: 1}` (i.e., that would only be > accessible via a method on that object? We already have properties which > are enumerable and writable, for example, independent of the class > mechanism. Why not have properties which are private in the same way? > > The problem,of course, is that even assuming the engines implemented the > `private` property on descriptors, I obviously don't want to have to write > `Object.create({}, {a: {value: 22, private: true})`. So the problem can be > restated as trying to find some nice sugar for writing the above. You > know, something like `{a<private>: 22}`. That's obviously a completely > random syntax suggestion, just to show the idea. Perhaps we'd prefer to > have the access modifiers be specifiable under program control as an object > itself, to allow something like > > ``` > const PRIVATE = {private: true}; > > const myObject = {a(<PRIVATE>: 2; } > ``` > > But what would the precise meaning of such as `private` descriptor > property be? In operational terms, it could suffice to imagine (as a > behavior, not as an implementation strategy) that objects would have a flag > that would skip over private properties when doing property lookups. I > think the right implementation is to have a private property look like it's > not there at all when access is attempted from outside the object (in other > words, is undefined), rather than some kind of `PrivatePropertyAccessError`. > > The above approach ought to be extensible to class notation: > > ``` > class Foo ( > bar<PRIVATE>(): { return 22; } > } > ``` > > which would end up being something like `Object.defineProperty(Foo.prototype, > "bar", {value() {return 22; }, private: true})`. > > Or when classes get instance variables: > > ``` > class Foo { > bar<PRIVATE> = 22; > ``` > > Was anything along these lines already brought up in this discussion? > > Bob > > > On Sat, Aug 4, 2018 at 12:30 AM Ranando King <[email protected]> wrote: > >> > It certainly doesn't look or feel like JS - it feels more like Java or >> C#. >> >> `private`, `protected`, `class`, and a few other such keywords have all >> been part of ES since long be for the TC39 board got their hands on it. >> They hadn't been implemented, but they were all a very real part of ES. Now >> that `class` has been implemented, it makes little sense to leave behind >> the `private` and `protected` keywords when we are trying to implement >> their functionality. >> >> > `private` looks like an identifier, and IMHO getters, setters, and >> async functions suffer the same issue of the keyword seeming to blend in a >> little with surrounding code. >> >> Have you ever thought that `var` or `let` look like identifiers? The >> `private` and `protected` keywords serve the same role as `var` and `let`: >> declaring a variable within a given scope or context. If you think there is >> a good logical or rational reason to avoid using the keywords that have >> been embedded in the language and left languishing, waiting for their >> meaning to be implemented, then I'm willing to entertain that. If the >> reason is based on mere feeling or emotion, well. I will only entertain >> such arguments if my reason for doing things a certain way is equally >> emotion based. Nothing I'm aware of in this proposal falls into that >> category. I have logical reasons for every choice I've made. >> >> >> 2. `protected` on an object literal is next to useless. I've used >> that kind of feature almost never. >> >> > And how would that be accessible? >> >> As you said, the vast majority of the time, this feature will go unused. >> However, when it's needed, it would look something like this: >> >> ```js >> var a = { >> protected sharedData: 1, >> increment() { ++this#.sharedData; }, >> print() { console.log(`sharedData = ${this#.sharedData}`); } >> }; >> >> var b = { >> __proto__: a, >> decrement() { --this#.sharedData; } >> }; >> ``` >> >> Setting `b.__proto__ = a` causes `b.[[PrivateValues]].__proto__ = >> a.[[PrivateValues]]`, `b.[[DeclarationInfo]].__proto__ = >> a.[[InheritanceInfo]]`, and `b.[[InheritanceInfo]].proto = >> a.[[InheritanceInfo]]`. So it all just works. >> >> > I saw `obj#['key']`, which *strongly* suggests dynamic keys are >> supported. >> >> Dynamic **_keys_** are supported. Dynamic **_properties_** are not! >> Please don't conflate the two. Dynamic keys are calculated property names. >> I am definitely supporting that. Dynamic properties refers to the ability >> to add and remove properties from an object at any time. I am not >> supporting that for private/protected members (unless someone can logically >> convince me it's a good idea). >> >> On Fri, Aug 3, 2018 at 1:02 PM Isiah Meadows <[email protected]> >> wrote: >> >>> Inline >>> >>> On Fri, Aug 3, 2018, 11:12 Ranando King <[email protected]> wrote: >>> >>>> > 1. It's *super incredibly boilerplatey* and verbose syntactically. >>>> >>>> I'm not sure what you mean by "boilerplatey". As for being verbose, I'm >>>> just using the keywords everyone understands for this purpose. IMO, there's >>>> no advantage in trying to find some shorthand to do the same thing just >>>> because it saves a keystroke or two when it makes the code significantly >>>> more difficult to understand. >>>> >>> >>> But on the same token, it's verbose enough that I feel readability >>> starts to suffer substantiallly. `private` looks like an identifier, and >>> IMHO getters, setters, and async functions suffer the same issue of the >>> keyword seeming to blend in a little with surrounding code. But those are >>> more like decorating the function than the name. >>> >>> Based on reading the several meeting notes, I don't believe the keyword >>> has been especially popular there, either. It certainly doesn't look or >>> feel like JS - it feels more like Java or C#. >>> >>> >>>> > 2. `protected` on an object literal is next to useless. I've used >>>> that kind of feature almost never. >>>> >>>> I get where you're coming from with that. I don't see it being used >>>> very often (kinda like `with`), but it has to be there. If someone wants to >>>> use the facilities of `class` without the limitations of the keyword, and >>>> the intent is to build vertical hierarchies, they'll need the "protected" >>>> keyword on their prototype definition to share private data with descendant >>>> factories. >>>> >>> >>> And how would that be accessible? Because you can't expose it via the >>> same way you do in classes without basically making them public (and >>> several workarounds suffer similar issues). >>> >>> > I also find it odd you're supporting private dynamic properties. >>>> >>>> How'd you get to the idea that I'm supporting dynamic private >>>> properties? >>>> >>> >>> I saw `obj#['key']`, which *strongly* suggests dynamic keys are >>> supported. >>> >>> > I actually think it's odd there is no attempt to implement dynamic >>>> properties in the other "private properties" proposals. >>>> >>> >>>> It's not that odd. There are issues around inheritance when a subclass >>>> can remove the `protected` properties of its base. Further, exactly how do >>>> you add a new `protected` property at runtime? Under both >>>> proposal-class-fields and proposal-object-members, there is never any >>>> direct access to the private container record, so use of >>>> `Object.defineProperty` will never work. IMO, any attempt to implement >>>> dynamic private properties in any sensible and consistent fashion would >>>> require somehow exposing the private data record to the code. That's a >>>> recipe for a private data leak. Not worth it. >>>> >>> _______________________________________________ >> es-discuss mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/es-discuss >> > > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

