constructor, super, and data members issue

Ranando King kingmph at gmail.com
Mon Sep 3 19:11:12 UTC 2018


Even with the suggestion I've made, I would still recommend keeping the
post-super() initialization function. It would simply get all of the class
fields from the prototype. Those that haven't already been initialized
would be, guaranteeing that all fields that need to be initialized would be
by the time they are needed in the code.

On Mon, Sep 3, 2018 at 2:05 PM Ranando King <kingmph at gmail.com> 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 <doodadjs at gmail.com>
> 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 <isiahmeadows at gmail.com>
>> Sent: Sunday, August 26, 2018 3:29 PM
>> To: Logan Smyth <loganfsmyth at gmail.com>
>> Cc: Ben Wiley <therealbenwiley at gmail.com>; es-discuss <
>> es-discuss at mozilla.org>
>> 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
>> contact at isiahmeadows.com
>> www.isiahmeadows.com
>>
>> On Sun, Aug 26, 2018 at 12:20 PM Logan Smyth <loganfsmyth at gmail.com>
>> 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 <isiahmeadows at gmail.com>
>> 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 <therealbenwiley at gmail.com>
>> 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 <isiahmeadows at gmail.com>
>> 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 <therealbenwiley at gmail.com>
>> 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 <
>> augusto.borgesm at gmail.com> a écrit :
>> >>>>>>
>> >>>>>> 24-08-2018 19:29, Aaron Gray <aaronngray.lists at gmail.com>:
>> >>>>>>
>> >>>>>> >
>> >>>>>> > 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 <ljharb at gmail.com>:
>> >>>>>>
>> >>>>>> >
>> >>>>>> > 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
>> >>>>>> es-discuss at mozilla.org
>> >>>>>> https://mail.mozilla.org/listinfo/es-discuss
>> >>>>>
>> >>>>> _______________________________________________
>> >>>>> es-discuss mailing list
>> >>>>> es-discuss at mozilla.org
>> >>>>> https://mail.mozilla.org/listinfo/es-discuss
>> >>
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> es-discuss at mozilla.org
>> >> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>>
>> ---
>> This email has been checked for viruses by AVG.
>> https://www.avg.com
>>
>> _______________________________________________
>> 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/20180903/a1b604cd/attachment-0001.html>


More information about the es-discuss mailing list