-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Grammar, Nodes: Class fields/class property initializers #4552
Comments
Is this the same as class properties, that are only in stage 2? See #4497 (comment) |
Bit of a brain dump incoming 😅 I did some digging into the current status of the public fields proposal. From what I can tell, this proposal to standardise orthogonal syntax for class properties is the bleeding edge for the standards work. The meeting notes I found this in are labelled for ES8, so there doesn't seem to be any concrete end in sight for standardising class properties due to various critiques about the semantics and syntax, and the dependencies between it and other proposals (e.g. private fields). In general, there seems to be a bit of stagnation in the standards around classes, and there's a whole other discussion about how tools such as babel make that work harder by providing early access to non-standard features like class properties, which people then conflate with standard ES features. There's no clear way for us to move forward here imo. We either:
As a bit of an aside, I think the main reasons to care about this feature at all are:
Let me know if I'm missing any! Separately, If anyone comes across this who has anymore information on how public properties is progressing on the standards track (or anywhere besides mailing lists and ESDiscuss to look for info), it'd be good to hear about it! |
I was really surprised class method binding is not available in CS2. It always was one of cs killer feature. I tried make it thru class properties and found out class properties is not working in CS2. It is not ES standard yet of course but look like will be. |
It seems some decisions were made at the latest es8 meeting - in particular the |
We can add support, but the compilation output would need to be Stage 4 ES (i.e. ES2017 or below). In other words, our version would need to resemble the Babel plugin, that converts the initializers syntax to ES5. And if or when the feature is standardized, our output could be updated to output ES2018 or whenever it lands, rather than the converted ES5 or ES2017. This is similar to the object destructuring being added in #4493. |
Here’s a good overview of current ES proposals. Some CoffeeScript-inspired ones on there. It covers the class-related ones that are in progress, including how they’ve been changing from stage to stage. |
I absolutely love this new feature and cannot wait for its implementation in CS. It looks like it's going to be at Stage 4 very soon. tc39/proposal-private-methods@7aa58d7 Note that there are both public & private fields, not mentioned in original post. The private field name is preceded by class Counter {
// public field
text = ‘Counter’;
// private field
#state = {
count: 0,
};
// private method
#handleClick() {
this.#state.count++;
}
// public method
render() {
return (
<button onClick={this.handleClick.bind(this)}>
{this.text}: {this.#state.count.toString()}
</button>
);
}
} |
I suggest usage of class Ex
::rand: -> Math.random()
::rand2: Math.random # CS shorthand?
private eq: -> @rand is @rand2
logEq: -> console.log @eq() |
Knock knock, it's already be included in Chrome 72: Public and private class fields | Web.
class IncreasingCounter {
#count = 0;
get value() {
console.log('Getting the current value!');
return this.#count;
}
increment() {
this.#count++;
}
} It looks like the
I think the double colons might be a little bit confused since it's the same syntax as static syntax (ex: |
Just to throw in two cents... I think that private fields and methods are going to be another "bad part" of JavaScript, and don't really have a place in a trusted code environment like the web. If I have a handle to a JS object, I should be able to inspect and manipulate every aspect of that object, and not have some parts of it locked away. We already have the enumerable/non-enumerable distinction, and writable/non-writable fields. I don't think private fields are necessary, or wise. If CoffeeScript left them out, it would be for the better. |
Well, I would say you are absolutely right. There are bunch of the weird things in JavaScript trying to confuse the programmers. We could ignore the private fields just like how we did to But and then we will need another document section to convenience people why CoffeeScript doesn't have private fields. |
We’re a long way from the days of In particular, even if we’re pretty sure something is a bad idea, if some other part of the JavaScript ecosystem like a framework requires that feature for full interoperability, then we need to support the feature in some way. Maybe the support will be like getters and setters, via something verbose like |
I've seen several people describing CoffeeScript as a "pythonic" JavaScript. I like the pythonic approach of OOP:
|
That may be true — but I thought that the point here is that private fields are private — they can't be seen, called, inspected, used, or touched by any other code. How could they be needed for interoperability? If there's a demonstration that can be made that proves it the other way, I'll withdraw my lament. |
So a framework like React involves a lot of So for example, say it becomes idiomatic in React to have a |
My current understanding of the private fields proposal — (note, I can't yet test it, because it isn't yet in Chrome Canary, so this may or may not be true...) — is that "Private fields are not accessible outside of the class body". Within the class body, you can refer to private fields on I guess we'll find out eventually... |
As an addendum, it's important to note that if subclasses were allowed to reference private fields, then they wouldn't be truly private. For any private field I wanted to get ahold of, I could simply: class SecretStealer extends Foo {
steal(foo) {
return foo.#privateData;
}
} Which reinforces my opinion that this isn't a great part of JavaScript ... if not a bad part, then a mediocre part, at best — either this class-based syntax doesn't work at all with class inheritance, or it isn't actually private in the first place. You can't have it both ways. |
@jashkenas To rephrase my example: If React documentation says, “define a private |
@GeoffreyBooth As Jeremy described, these are not accessible outside of the class declaration, so no API should "theoretically" require them. I think there probably will be some way of getting at these values, as should be accessible for browser tooling, but maybe those APIs will be restricted to browsers, their tools and maybe extensions (not sure, I'm not an expert). I am not a fan of the ES proposal, simply because I have had bad experiences in the past with API authors not exposing things I needed (in languages that didn't allow reflection). Private (via mangling) fields have been used at FB for a very long time successfully, but with those I can always do (also, wow, totally forgot I filed this, and also, this issue was just about the compilation strategy / syntax / typing, the issue of private fields is a different beast) |
As i understand, it would transpile to a class Ex
private abc: 123
eq: (x) -> x is @abc being functionally equivalent to: class Ex
_privates = new WeakMap
constructor: ->
_privates.set this,
abc: 123
eq: (x) -> x is _privates.get(this).abc Babel currenly offers [Class Private Instance Fields] (aren't private at all, they might have dropped a bad link) and [Static Class Fields, Private Static Methods]. Private statics are already well possible in coffeescript, the snippet above uses one. |
Posting here for reference. 2ality has two relevant articles (so far): Notably, these ES proposals are still at stage 3. |
Here are the relevant proposals:
They’re all Stage 3, and most (if not all) have shipped in Node and Chrome, so they should be ready for implementation for anyone who wants to tackle them. Obviously we need to choose a different syntax than |
I went to create a new issue about this, but then found this issue exactly about instance fields. The difference is that instance fields are now in ECMAScript (both public and private, but I'm focusing on public here). I propose modernizing CoffeeScript's output to use class fields. Consider the following input: class Foo
i = 1
j: 2
@s: 3
sum: -> i+j+s The current output builds a closure to simulate a private variable var Foo;
Foo = (function() {
var i;
class Foo {
sum() {
return i + j + s;
}
};
i = 1;
Foo.prototype.j = 2;
Foo.s = 3;
return Foo;
}).call(this); The clearest change is that class Foo {
static s = 3;
} I propose that var Foo;
Foo = (function() {
class Foo {
i = 1; // note: no 'var i'
static s = 3;
sum() {
return i + j + s;
}
};
Foo.prototype.j = 2;
return Foo;
}).call(this); The difference between class Foo
fresh = {}
stale: {}
a = new Foo
b = new Foo
console.assert a.fresh != b.fresh
console.assert a.stale == b.stale My desire for public instance field syntax in CS output comes from supporting TypeScript (#5307). In TypeScript, you need to declare This would be a breaking change, though. In the proposal, |
From above:
When CoffeeScript 2 launched, there was a note (maybe just for object destructuring, or at least most prominently for object destructuring) that if/when ECMAScript caught up to us for some of the features we’re compiling down to ES5, we would update our output to match the finalized ES spec, even if it was a slight breaking change. If it’s a huge breaking change then I think we need to keep what we have, but if it’s an edge case that’s unlikely to be affecting most code then I think it’s fine to include in a semver-minor bump with clear documentation. |
We should be able to write the equivalent of
Can it be
or does the
b
property have different semantics?The text was updated successfully, but these errors were encountered: