constructor, super, and data members issue

Jordan Harband ljharb at gmail.com
Mon Sep 3 20:51:34 UTC 2018


`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 <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
>>
>
> _______________________________________________
> 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/808af98e/attachment-0001.html>


More information about the es-discuss mailing list