Closed littledan closed 5 years ago
If we add static blocks, then code which would be written as
class C {
static x = 1;
static y = 2;
}
could instead be written
class C {
static {
this.x = 1;
this.y = 2;
}
}
Would that sort of syntax be an adequate replacement for static public fields for you? (My personal impression: It's not a sufficiently ergonomic replacement.)
Would that sort of syntax be an adequate replacement for static public fields for you?
This biggest loss here is the declarative nature of class fields. It's certainly an option to put it in a (imperative) statementlist, but doing that is only slightly better that just putting the C.x = 1
after the class declaration.
In general, public properties on the constructor are conceptually “part of the class”. Having things that are part of the class, but can’t be declared declaratively in the class body, is a loss - and more specifically, is a massive oversight in the design of ES2015 classes.
Angular is also using static class property for storing compiled template (and other metadata) in its next-generation compiler, like:
class CounterComponent {
count = 0;
static ngComponentDef = defineComponent({
type: CounterComponent,
selectors: [['counter']],
template: function(ctx: CounterComponent, cm: boolean) {
if (cm) { text(0); }
textBinding(0, bind(ctx.count));
},
factory: () => new CounterComponent,
inputs: {count: 'count'},
});
}
One of my concern is that, since the stage-3 private class fields is lexical, so using static class fields annotation should allow the private fields usage in template, like:
class CounterComponent {
#count = 0;
static ngComponentDef = defineComponent({
template: function(ctx: CounterComponent, cm: boolean) {
textBinding(0, bind(ctx.#count));
}
});
}
But the assignment should not:
class CounterComponent {
#count = 0;
}
CounterComponent.ngComponentDef = defineComponent({
template: function(ctx: CounterComponent, cm: boolean) {
textBinding(0, bind(ctx.#count)); // Error here
}
});
So the existence of static public fields should be meaningful for the template accessibility. (The static initialization block should also helped)
Static class fields are used somewhat elegantly for config in React Navigation (a popular navigation lib for React Native). One example from their doc, showing how a static navigationOptions
field on component classes is used to override the base config for a group of components.
Of course it can be achieved in the ES2015 way too:
class MyComponent {
…
}
MyComponent.navigationOptions = { … }
It’s just not very elegant.
https://searchfox.org/mozilla-central/search?q=static&case=true®exp=false&path=.webidl (this includes a bit of noise though; not all is web-exposed).
I agree with @ljharb And quite frankly, I don't understand the skepticism... other than maybe a political power play.
Static fields are used in every language I know of where classes are a thing. Even old js frameworks that defined their own class system had a concept of statics. These belong in the language.
Some use cases that come to mind beyond React's static propTypes
is static factory methods, or type mapping. I have a library of models and each model statically defines a static MimeType... I don't think the use cases can be adequately enumerated.
@jsg2021 Most of the skepticism arises because the semantics of static public fields in JavaScript will not match the semantics some of those in some nontrivial faction of cases. (Note: I personally support them; I just want to explain why this is an issue.)
In particular, in Java, this code
class Base {
static int i = 0;
}
class Derived extends Base {}
Derived.i++;
print(Derived.i, Base.i);
would print
(1, 1). (C# behaves similarly, among other languages.)
In JavaScript, the same code (leaving out the int
type declaration) would print
(1, 0). See discussion in #5, #24, etc.
On the other hand, static public fields in Python classes behave like they are proposed to do in JS with regards to the above inheritance behavior. There's no universal agreement on what the semantics for inheritance should be.
This is somewhat off-topic for this thread, and discussion of these semantics should go in other threads if you want to continue it. Just wanted to respond to your comment.
I see. Thank you for the insight. This is helpful.
I have observed this behavior you described. I felt it was intuitive... kind of a copy-on-write kind of thing. I don't want to derail this thread, so thats all I'll say :)
@bakkot
semantics of static public fields in JavaScript will not match the semantics some of those in some nontrivial faction of cases.
This is already the case:
class List extends Array {}
console.log(List.from === Array.from); // true
List.from = "literally anything else";
console.log(List.from === Array.from); // false
If user code wanted those semantics, they could implement them:
let Base;
{
let i = 0;
Base = class {
static get i() {
return i;
}
static set i(value) {
i = value;
}
}
}
class Derived extends Base {}
Derived.i++;
console.log(Derived.i, Base.i);
Let's keep this thread limited to the use cases for static public fields; we can discuss reservations anyone might have about their semantics on other threads in this repo.
SkateJS uses public static fields to define props.
Below is an example of a SkateJS component class declaration. props
field is used by the framework, events
by the application:
export default class extends Component {
static events = ["check", "remove"];
static props = {
checked: props.boolean,
index: props.number
};
//..
}
Actual code: https://github.com/vogloblinsky/web-components-benchmark/blob/master/todomvc/skatejs-preact/src/item.js
Thanks for the examples here. Seems like we have plenty of justification for static public fields, and based on this justification, the proposal has re-achieved Stage 3 in TC39.
In the March 2018 TC39 meeting, some committee members expressed skepticism for static public fields. We know that static public fields are heavily used in React's class-based components, but it's not so transparent to the whole committee what other applications JS programmers have in mind for static public fields. What would you like to use static public fields for?