-
Notifications
You must be signed in to change notification settings - Fork 113
Default placement of instance properties (prototype vs. instance) #33
Comments
I agree there's a typo in the spec text; both
Fields are installed before the body of the constructor executes (or at the start of the In any case, this has been discussed at length already in tc39/proposal-class-public-fields#59. Ultimately, putting fields on the prototype seems likely to do more harm than good, even if there are use cases for it. |
Thanks for the explanation. Ah, so in this proposal, the properties are initialized before the call to
This is also the only way to transpile it to ES6 with conventional class syntax, since you can't do But if the real implementation will do this behind the scenes somehow:
Then yes, that would solve it. Alternatively (or in addition), maybe there could be some methods on |
Sorry, I'm mistaken, instance fields on subclasses are initialized after the call to |
It kind of seems like your |
I think it's reasonable to want to implement this idiom as written...basically the idea is to create a plain old JS object but with the ability to set all the parameters at once in the constructor - and ignoring any extraneous properties that might be passed in. I'm not sure how using an object or Map would help with this particular problem, unless you mean passing the attribute map as an argument to the constructor like this:
...but that defeats the purpose of using a base class to assign the attributes (which was intended to reduce boilerplate code). And it allows invalid attributes to be added to the object. So I guess I'm just not following you. Anyway, this is just one use case for wanting to reflect on instance property names. I can imagine other potential scenarios...for example, if you had a constructor with required parameters, with the current proposal the only way you could find out the property names from outside the class would be to actually create an instance (requiring specific knowledge of how to call that particular constructor). But there are many ways to accomplish reflection, and I take your point that defaulting to putting properties on the prototype could be problematic. So perhaps I should close this issue and file a new one specifically about reflection. |
Closed in favor of #36. |
It looks like in the current proposal, public properties declared without the
static
modifier are added to the instance by default, i.e. this:Translates to this:
I'm a little confused when looking at the spec though, specifically this part of
DefineField()
(last step):Perform ? DefinePropertyOrThrow (F, fieldName, desc).
I may be reading it incorrectly, but I thought that
F
was a reference to the constructor function / class - makes me wonder if it was a typo and it was supposed to beO
there instead ofF
, but I'm not well-versed in reading these specs so maybe not.In any case, assuming my understanding is correct that properties will go on the instance by default, I wanted to bring up two previous threads on this subject:
tc39/proposal-class-public-fields#38
tc39/proposal-class-public-fields#59
People have brought up a number of good reasons why it would be good for properties to go on the prototype by default. Here's an example use case where the difference matters:
If the fields are only defined on the instance, then the parent class has no way of knowing about them in the constructor.
I saw @littledan's comment in #3 that the current proposal leaves open the possibility of modifiers (e.g.
own
andshared
) to explicitly specify where properties should be defined. I think that's a great idea, but I still think the prototype is a better default than the instance, at least for primitives. It could of course be problematic for object and array properties - those shouldn't be shared by default among instances, and if they were it would be surprising and a source of bugs. But it would be simple enough to set all non-primitives to null on the prototype and set their real initial values in the constructor (perhaps only if the parent constructor(s) didn't already initialize them - not sure about that part). Actually, even primitives could be set to null on the prototype if there is some reason that it would be better not to set their initial values there (although I can't think of one). The main concern I wanted to bring up is that the properties declared inside the class should somehow be visible on the prototype -- even if only the property names and not their real default values.There may be other, better solutions to the use case above. I suppose what I'm really advocating is some kind of ability to do reflection on instance properties from parent classes or outside the class scope entirely (without needing to actually create an instance to do it). So I'd be interested to hear any alternative suggestions, or further explanations as to why the current proposal is as it is.
The text was updated successfully, but these errors were encountered: