-
Notifications
You must be signed in to change notification settings - Fork 25
Computed property name evaluation order #44
Comments
Also, we should be careful with the evaluation order of static properties. Consider: class C {
static [console.log('a')] = null;
static a = console.log('b');
static [console.log('c')] = null;
} Should this print 'a', 'b', 'c', or 'a', 'c', 'b'? I believe the former (interleaving initializer evaluation with property name evaluation) is more correct, but whichever is chosen it should be deliberate. |
Consider: class C {
[console.log(1)] = console.log("during construction");
static [console.log('a')] = console.log('b');
[console.log(2)](){}
static a = console.log('c');
static [console.log(3)](){}
static [console.log('d')] = null;
} I believe the log order should be 1, 'a', 'b', 2, 'c', 3, 'd'. This can be accomplished in ClassDefinitionEvaluation by merging the logic of steps 24-32 into the loop of step 21. Basically, handle each ClassElement separately and in order. You can probably simplify the conditional logic by defining PropertyDefinitonEvaluation logic for static and instance field ClassElements. |
Agree with OP, but IMO the model that makes most sense here (and presented to TC39 previously) is one where computed property keys are evaluated first, in order, followed by other evaluation steps such as evaluating static initializers. I hope we can make this true even for object literals (got tentative approval for this few meetings back pending investigations into the feasibility). |
Anything other than lexical order (left-to-right, top-to-bottom) seems completely arbitrary and hence much harder to learn and remember. Particularly since lexical order is the ordering that is applied almost everywhere else in JS. Such Inconsistencies is an indication of incoherent design. What is the rationale for doing computed property keys out of that natural order? |
Computed property keys should be in order. Other expression positions may not be computed in order. This is obvious with instance field initializers which cannot be evaluated in order, so why would you expect static field initializers to be evaluated in order (edit: with respect to computed property keys, static field initializers should be initialized in order with respect to other static initializers) |
Only instance fields (and private) initializers are deferred until construction time so can't follow that order. class C {
[computedKey+console.log(1)]; //computing key part of class evaluation
static A = console.log(2); //computing static initializer value part of class evaluation
[computedInstanceKey+console.log(3) //computing key part of class evaluation
= console.log("ctor-time 1"); //initializer evaluated during construction
static [computedKey+console.log(4)] = console.log(5);
//both key and init value computation part of class eval
[computedInstanceKey+console.log(6) //computing key part of class evaluation
= console.log("ctor-time 2"); //initializer evaluated during construction
} Any other ordering is more complicated and arbitrary. Hard to remember. Instance and instance keys interweaved or separate? Instance keys before static keys?? static keys before instance keys? static initializers before or after instance keys? What's the easy to learn remember rationale? Left-to-right/top-to-bottom for separately for both class evaluation time and construction time is the simplest story. |
You have to remember something either way - either you remember that static initializers are evaluated in order interleaved with computed property evaluation unlike every other expression position in the class body, or you have to remember that, like any other expression position, the evaluation order is different from top-down-left-right (edit: and what that is). IMO the proposal we discussed in TC39 earlier is easy to remember: Step 1: the shape of the declaration is obtained by evaluating all computed property keys in order. |
@allenwb, while I personally agree with you, I understand that (part of) the motivation for evaluating static initializers after the rest of the class is so that they can refer to the class, e.g.: class C {
static singleton = new this;
constructor() { ... }
[prop] = val;
} Personally I am opposed, and think that we shouldn't mess with the usual evaluation order without very strong reason. @bterlson, what other expression positions are there / do you anticipate there being, in class bodies? Method bodies and field initializers are of course evaluated later, but I don't think that's surprising. Decorators would happen before the rest of the class, I suppose? |
@bakkot For decorators on methods/fields the decorator expression are evaluated in order interleaved with computed property expressions (it's part of the "create the shape of the class" step) but decorator functions are evaluated at various points depending on what you're decorating. |
Consider
As spec'd, evaluating this class expression would print
2 1 3
. This seems clearly wrong; computed property names should be evaluated in the order in which they appear.The text was updated successfully, but these errors were encountered: