-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Design Meeting Notes, 6/9/2017 #16415
Comments
Just a comment with the ES5 down-emit with private members, if you considered the async/await down emit pattern by assuming |
Also from a @dojo perspective we have debated a lot of putting private state in weak maps. We just know that if it is accessible, people will abuse it and the only way to to ensure it to promote it being truly private. The biggest challenge is that we have in some cases run into having to name privates in descendent classes silly things because of private member name conflicts, which makes code unclear. |
And P.S. I hate the syntax for the record too... 😂 |
Hey, thanks for the feedback about the syntax. The rationale is documented in the FAQ. Does anyone have any other suggestions?
What's the concern here? |
@littledan The FAQ doesn't address why the octothorpe ( I would think the js community would prefer the underscore ( |
The problem is that would break the internet, because the runtime engine must lookup the property differently. If every |
@styfle This is a great point. I added a new FAQ entry to explain the reasoning. |
@littledan Excellent, thank you for the detailed write up! I submitted a PR with some typo fixes. I noticed the proposal-private-fields is Stage 1 but the proposal-class-fields is Stage 2 and seems to include private fields. Is this expected and if so, why? |
Why WeakMaps not closures? |
@mihailik Because there's still just one method identity on the prototype, rather than the instance. |
A rough prototype (play with it on CodePen) function Apple() {
// carrying private state
function Private() {}
Private.prototype = this;
var private = new Private();
// bind methods to private state
this.getColor = private.getColor.bind(private);
this.setRed = private.setRed.bind(private);
this.setGreen = private.setGreen.bind(private);
}
Apple.prototype.setRed = function() {
this._color = 'red';
this.constructor.prototype.caption = 'Red Apple'; // mutating of public state, a bit convoluted
};
Apple.prototype.setGreen = function() {
this._color = 'green';
this.constructor.prototype.caption = 'Green Apple'; // mutating of public state
};
Apple.prototype.getColor = function() {
return this._color;
};
var s = new Apple();
s.setRed();
console.log('setRed: ', s.getColor(), s.caption, s._color);
s.setGreen();
console.log('setGreen: ', s.getColor(), s.caption, s._color);
s.caption = 'Orange Apple?';
s._color = 'orange';
console.log('mutating directly: ', s.getColor(), s.caption, s._color); |
Bound methods are being pursued separately, cc @rbuckton In some engines, using bound methods all the time is slower. Anyway, ES6 |
Having to re-bind methods for each instance is the cost of implementation using closures. Is WeakMap implementation cheaper? Not obvious. Especially considering nontrivial performance/GC/JIT pressures of WeakMap. Closure implementation has another win: it works on ES5 too. |
Besides, the approach works when emitting ES6 classes too (again, CodePen to try): class Apple {
constructor() {
// carrying private state
function Private() {}
Private.prototype = this;
var _private = new Private();
// bind methods to private state
this.getColor = _private.getColor.bind(_private);
this.setRed = _private.setRed.bind(_private);
this.setGreen = _private.setGreen.bind(_private);
}
setRed() {
this._color = 'red';
this.constructor.prototype.caption = 'Red Apple'; // mutating of public state, a bit convoluted
}
setGreen() {
this._color = 'green';
this.constructor.prototype.caption = 'Green Apple'; // mutating of public state
}
getColor() {
return this._color;
}
}
var s = new Apple();
s.setRed();
console.log('setRed: ', s.getColor(), s.caption, s._color);
s.setGreen();
console.log('setGreen: ', s.getColor(), s.caption, s._color);
s.caption = 'Orange Apple?';
s._color = 'orange';
console.log('mutating directly: ', s.getColor(), s.caption, s._color); |
If you're talking about how TypeScript should implement this, then the desugaring you have there has observably different semantics than the spec. In particular, you can If you're talking about what semantics to adopt to be efficiently implementable: WeakMaps in V8 aren't the fastest, but private fields will allow implementation with V8's internal-only "private symbols", which are more efficient. Not sure about other engines. |
True! Desugaring is already observably different of course — so it's a matter of weighing pros and cons. Besides, I think the whole approach may be worth considering in JS spec as well. Using It's more complex in the engine, but much benefit for the coders, and more sane mental model. |
This isn't an engine issue, it's a language design issue. Please refer to the private fields FAQ to find documentation for the design. I hope the TypeScript team tries to minimize observable differences, though I understand this isn't always possible. If differences are minimized, there will be a smaller "bump" for users who come from or to standard JS. In this case, which receiver is used is a pretty big difference. |
@littledan out curiosity, in which practical case you expect this be observed? In which cases do people define methods on a class, only to bind it to something else? The JS FAQ is cautious on |
There is extensive discussion of this in the TC39 proposal. No good re-hashing it here, on an issue about the TypeScript implementation of the proposal. It would be best to focus the discussion in the proper forum, which considers the matter closed. |
As usual I'd echo what @kitsonk just said |
My closure-based suggestion is related to TypeScript. Any comments on that, regardless of JS implementation? |
@mihailik I'd encourage TypeScript to not use that kind of closure-based implementation, since it'd diverge from the possible native implementations in a pretty major way. TypeScript users may start depending on this behavior and be disappointed when they have to change their code later. |
Stricter generic signature checks
any
.a = b
above, it simulates callingb
witha
's parameters.master
and see what we can work with.Private Slots
Proposal: https://github.com/tc39/proposal-private-fields/ (Permalink)
Repo: https://tc39.github.io/proposal-private-fields/
How does this work with existing modifiers?
Can we offer a true downlevel translation?
Could give a mangled name in ES5/ES3.
What about using Symbols in ES6?
Weakmaps make it truly private.
P.S.
everyone hates the syntax.we're not big on the syntaxCompletely unrelated
We'll all need to go over the FAQ more closely on the private state proposal repo.
The text was updated successfully, but these errors were encountered: