Le 18/01/2013 06:47, Russell Leggett a écrit :
On Thu, Jan 17, 2013 at 9:40 PM, Kevin Smith <khs4...@gmail.com
<mailto:khs4...@gmail.com>> wrote:
It seems as if this approach to private class members also allows
us to describe private methods in a convenient way. Private
methods can be attached to the _prototype_ of the private field
object, thus avoiding per-instance allocation. Of course, the
correct "this" value has to be used in the expansion when calling
the private method, but this approach appears to be compatible
with mixins (whereas private symbols are not).
https://gist.github.com/4561871
Thoughts?
I've been on the fence with the debate, but I'll admit that this
proposal is really winning me over. I don't know if it's too late to
get this syntax in, but it would be a major win for me.
syntax details aside (especially with Domenic improvements), I agree.
I like this a lot more than private symbols.
Assuming the only valid use case for private symbols is classes, I agree
It actually feels a lot like deconstructing an abstract data type or
pattern matching a case class in scala. There is something nice about
keeping all that extra stuff off the actual object. I'm not sure if
I'd still like it as much without the syntax, but maybe I would now.
I have do have a few questions on this, though:
1. How does this interact with proxies? I'm guessing that a proxy will
not map correctly and therefore make it inaccessible. Personally, I'm
ok with that.
It does not interact that well because of the this-binding. Classes have
been long expected, so will be used, so proxies have to work well with them.
class Purse {
private balance;
constructor(balance = 0) {
private.balance = balance;
}
getBalance() { return balance; }
}
var p = new Purse(6);
var pp = new Proxy(p, {});
console.log(pp.getBalance());
We should be able to expect p and pp to act the same in all
circumstances. With Kevin's expansion, pp.getBalance() throws a
TypeError, because "amp.get(this)" is not an object.
Proxy authors can work around that by returning functions bound to the
target, but this is not free obviously (create as much bound functions
as there are of (instance, method) pair).
The interaction between private syntax and proxies has the following
components:
1) Do the proxy and the target act the same regarding private properties?
The answer is yes with whitelisted private symbols, no with naive
weakmap-expanded private syntax (I explain non-naive below)
I think the answer should be yes here.
2) Does the proxy has a word to say about the access to the private
property?
It's yes with private symbols (different trap if whitelisted or not).
The answer is yes for weakmap-expanded private syntax, but with some
explanation. The proxy can't know about the private property, however,
every access to something private has to be performed through something
public (public accessor or method). Indeed, the class encapsulate access
to private state (this isn't true of private symbols in general). Since
the proxy can cut communication of public accesses, it can also cut
accesses to private properties. I think that this additional simplicity
weighs in favor of the removal of private symbols.
(I had a third point in mind and I forgot it...)
Above I've talked about naive weakmap-expanded private syntax. A less
naive version could "override" the Proxy constructor to know about proxy
-> target associations. Access to private state wouldn't start with the
naive "amp.get(this)", but rather with "amp.get(proxyToFinalTarget(this)
|| this)". ("finalTarget" in case the target of the proxy is itself a
proxy).
For native syntax, we can imagine this setup exists before any code
runs. The transpiler story is a bit less clear to me. I see different
ways of writing class transpilers with different properties:
1) make classes incompatible with proxies
2) share (aka "leak") the proxyToFinalTarget function to transpiled classes
3) bring the full transpiler in the runtime so that classes can work
with proxies (only the transpiler has access to proxyToFinalTarget)
I think different users in different contexts all have a solution to
their need.
2. Can I use private as a normal variable? Can it be bound to a new
variable, passed as an argument, or returned from a function?
constructor(balance = 0) {
let p = private;
p.checkNum(amount);
p.balance = balance;
}
I would understand not going this route, but it definitely restricts
access very tightly where private member or manually using a weakmap
would allow it. Perhaps that edge case can just be handled by falling
back to manually using a weakmap.
Mark's point about private symbol being mostly useful in the context of
class convinced me that pretty much every other context can work with
WeakMaps.
No opinion on your third point.
David
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss