I'd say that defining a class directly in a class field is extremely niche, and by doing that, the user "should know what they've done" too.
On Mon, Sep 3, 2018 at 3:44 PM, Ranando King <[email protected]> wrote: > That scenario is intentional. I see no need to ban it. I would only want > to ban the confusing case of direct assignment in the outer class > declaration. For cases where the user intentionally defines a class as you > have done, they should know that what they've done will create a class that > is persistently re-defined with each instance. As has been said many times > before, it's good to reduce the number of foot-guns, but at some point, you > have to expect some level of responsibility from the programmer. Consider > that rule as little more than a safety switch. > > On Mon, Sep 3, 2018 at 3:52 PM Jordan Harband <[email protected]> wrote: > >> `field = (function () { return class { }; }())` - how exactly would you >> propose banning creating a class inside class fields? >> >> On Mon, Sep 3, 2018 at 12:05 PM, Ranando King <[email protected]> wrote: >> >>> I've been thinking about the problems around this some more. At first I >>> couldn't get past the dissenting arguments from issue #123, but I've since >>> come up with a solution that might work. What if: >>> >>> * Make it illegal to define a class directly on a class field in a class >>> declaration. >>> * Move the assignment portion of a class field declaration into a getter >>> on the prototype such that the getter sets an own property on the instance >>> if it doesn't exist, then returns that value >>> >>> What I mean is this: >>> >>> ```js >>> class Example { >>> //classField = class{}; //Error >>> otherField=[ "foo", "bar"]; >>> } >>> >>> class ES6Example { >>> //classField ignored for this example since it was an error. >>> get otherField() { >>> if ((this instanceof ES6Example) && !this.hasOwnProperty(" >>> otherField")) >>> this.otherField = [ "foo", "bar" ]; >>> return this.otherField; >>> } >>> } >>> ``` >>> >>> Done this way, any code expecting early assignment of a field being used >>> as though it were "abstract" will still work as expected. >>> >>> On Thu, Aug 30, 2018 at 4:38 PM doodad-js Admin <[email protected]> >>> wrote: >>> >>>> I'm late to the party, but I've found a solution for my non-loved >>>> framework : have another constructor called before "super", which fills a >>>> faked "this" and a faked "args" then replicated values to "this" after >>>> doing "super(...fakedArgs)". >>>> >>>> https://github.com/doodadjs/doodad-js/blob/v9.1.3/src/ >>>> common/Bootstrap.js#L5320-L5330 >>>> >>>> -----Original Message----- >>>> From: Isiah Meadows <[email protected]> >>>> Sent: Sunday, August 26, 2018 3:29 PM >>>> To: Logan Smyth <[email protected]> >>>> Cc: Ben Wiley <[email protected]>; es-discuss < >>>> [email protected]> >>>> Subject: Re: constructor, super, and data members issue >>>> >>>> Yeah, I was more focused on the static class side of things, because I >>>> thought they were referring to that. Class instance fields are different, >>>> and so of course, those are never set on the prototype unless for whatever >>>> reason, the parent constructor returns `Object.getPrototypeOf(this)` >>>> instead of letting it default to the normal `this`. >>>> >>>> My bad, and you are correct. >>>> >>>> ----- >>>> >>>> Isiah Meadows >>>> [email protected] >>>> www.isiahmeadows.com >>>> >>>> On Sun, Aug 26, 2018 at 12:20 PM Logan Smyth <[email protected]> >>>> wrote: >>>> > >>>> > Static class fields run their initializers and define the properties >>>> > at declaration time, and class constructors have the parent class as >>>> > the `[[Prototype]]`, so static field values are inherited. I think >>>> this is adding to confusion though, because while that's absolutely true, >>>> that is not applicable in the same way to non-static class fields, which is >>>> what this original email is focused on. You could indeed also address this >>>> with static properties in a proper ES6 environment as ``` class Base { >>>> > static idAttribute = "id"; >>>> > >>>> > constructor() { >>>> > this.idAttribute = new.target.idAttribute; >>>> > } >>>> > } >>>> > class Derived extends Base { >>>> > static idAttribute = "_id"; >>>> > >>>> > constructor() { >>>> > super(); >>>> > } >>>> > } >>>> > ``` >>>> > >>>> > On Sun, Aug 26, 2018 at 10:35 AM Isiah Meadows < >>>> [email protected]> wrote: >>>> >> >>>> >> Every object, including functions, have an internal prototype. >>>> Functions normally have one set to `Function.prototype`, and objects >>>> normally inherit from `Object.prototype` at least indirectly. But because >>>> of how prototypes work, the only requirement for something to be used as a >>>> prototype is that it must be an object. So you can do >>>> `Object.create(someFunction)` and although you can't call it (it's not a >>>> callable object), that object inherits all the properties and methods from >>>> that function. `class` in JavaScript is just sugar over a common pattern >>>> (really complex sugar requiring `new.target` to emulate, but still sugar), >>>> not an entirely new concept, and it all builds off of prototypes. >>>> Specifically, the instance prototype inherits from the parent prototype, >>>> and the class constructor itself inherits from the parent constructor. >>>> That's why if you declare a static `call` method on a parent class, you can >>>> still access and use it in the subclass. >>>> >> On Sat, Aug 25, 2018 at 19:58 Ben Wiley <[email protected]> >>>> wrote: >>>> >>> >>>> >>> How can they be prototypically inherited if they don't live on the >>>> prototype? I feel like I'm missing something. >>>> >>> >>>> >>> Le sam. 25 août 2018 19 h 53, Isiah Meadows <[email protected]> >>>> a écrit : >>>> >>>> >>>> >>>> Class fields are prototypically inherited just like via `Object >>>> create`. This is more useful than you might think, and it's the main reason >>>> anyone actually cares about static fields beyond namespacing. >>>> >>>> On Sat, Aug 25, 2018 at 14:36 Ben Wiley <[email protected]> >>>> wrote: >>>> >>>>> >>>> >>>>> All this just reminds me of *my opinion* that class fields is a >>>> borrowed concept from statically typed languages that is misplaced in a >>>> dynamically typed languages like JavaScript. >>>> >>>>> >>>> >>>>> In C++ I use class fields to declare what properties will be >>>> allocated and instantiated when a new class member is constructed. >>>> >>>>> >>>> >>>>> In the ES proposal for class fields we mimic this type of >>>> behavior by instantiating properties on the object when it's constructed, >>>> but there's no runtime guarantee that this set of properties will remain >>>> the same. >>>> >>>>> >>>> >>>>> There's no reason not to put this in the constructor, and >>>> although putting class fields on the prototype is debatably not the best >>>> idea, it would be the only scenario where we get some kind of new helpful >>>> behavior out of it. >>>> >>>>> >>>> >>>>> Ben >>>> >>>>> >>>> >>>>> Le sam. 25 août 2018 14 h 25, Augusto Moura < >>>> [email protected]> a écrit : >>>> >>>>>> >>>> >>>>>> 24-08-2018 19:29, Aaron Gray <[email protected]>: >>>> >>>>>> >>>> >>>>>> > >>>> >>>>>> > Yeah it does look like its badly "broken by design". >>>> >>>>>> > >>>> >>>>>> >>>> >>>>>> Why this behaviour is broken? Every OOP language that I worked >>>> >>>>>> with behaves de same way, and there's not many developers >>>> >>>>>> complaining about it. If you want to use a property that might >>>> be >>>> >>>>>> overrided in a subclasss you need to use a method and make the >>>> >>>>>> source of the data more versatile (in Java and others similiar >>>> >>>>>> languages we have to implement it using getter methods). Luckily >>>> >>>>>> Javascript doesn't need getter and setters methods to make a >>>> >>>>>> property overridable because of getter and setters descriptors, >>>> >>>>>> so we can workaround the first example >>>> >>>>>> easily: >>>> >>>>>> >>>> >>>>>> ``` js >>>> >>>>>> class Bar { >>>> >>>>>> bar = 'in bar'; >>>> >>>>>> >>>> >>>>>> constructor() { >>>> >>>>>> console.log(this.bar) >>>> >>>>>> } >>>> >>>>>> } >>>> >>>>>> >>>> >>>>>> class Foo extends Bar { >>>> >>>>>> _initiedSuper = false; >>>> >>>>>> _bar = 'in foo'; >>>> >>>>>> >>>> >>>>>> constructor() { >>>> >>>>>> super(); >>>> >>>>>> this._initiedSuper = true; >>>> >>>>>> } >>>> >>>>>> >>>> >>>>>> get bar() { >>>> >>>>>> return this._bar; >>>> >>>>>> } >>>> >>>>>> >>>> >>>>>> set bar(val) { >>>> >>>>>> if (this._initiedSuper) { >>>> >>>>>> this._bar = val; >>>> >>>>>> } >>>> >>>>>> } >>>> >>>>>> } >>>> >>>>>> >>>> >>>>>> new Foo(); // will log 'in foo' >>>> >>>>>> ``` >>>> >>>>>> >>>> >>>>>> *I have to say the relaying that the super constructor will use >>>> >>>>>> the bar property and workarounding it **is a bad practice** and >>>> >>>>>> should be avoided at any costs. The contract with the super >>>> class >>>> >>>>>> constructor should rely only on the super call, these situations >>>> >>>>>> just reveal bad design choices in the super class. Logan Smyth >>>> >>>>>> example is the correct answer to this problem* >>>> >>>>>> >>>> >>>>>> >>>> >>>>>> 25-08-2018 01:28, Jordan Harband <[email protected]>: >>>> >>>>>> >>>> >>>>>> > >>>> >>>>>> > Personally I think a design where the superclass relies on any >>>> >>>>>> > part of the subclass is "broken by design"; but certainly >>>> >>>>>> > there's ways you can achieve that. >>>> >>>>>> > >>>> >>>>>> >>>> >>>>>> Of course is not broken. The super class has a contract with a >>>> >>>>>> parametrized option, it can be used in subclasses or just in a >>>> >>>>>> constructor call `new Base({ idAttribute: 'foo' })`, if it has a >>>> >>>>>> default value for that is not a sub class concern. When >>>> >>>>>> refactoring code adding defaults and "lifting" parameters are >>>> >>>>>> very common ~not only on OOP~ and relying that the super class >>>> is >>>> >>>>>> using some property in the constructor is the real "broken by >>>> design". >>>> >>>>>> _______________________________________________ >>>> >>>>>> 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 >>>> >>>> >>>> >>>> --- >>>> This email has been checked for viruses by AVG. >>>> https://www.avg.com >>>> >>>> _______________________________________________ >>>> 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

