If I can add my point to the discussion, I must admit I don’t like the “Private
Names Proposal” either. I find it confusing and complex. As I thought I was the
only one who had this in mind, I didn’t react before but if more people are
confident it’s a strange proposal, maybe could the proposal be replace by
something simpler and more intuitive.
When I first read the proposal, I thought we may use a new property of the
property descriptors to define the “privality” of a property.
What I propose is to manage a list of all currently defined private keys. This
list is managed scope by scope. Each time a <<private key>> instruction is
encountered, the value of the private key that follows (or, if undefined, a new
private key) is added to private keys list (shortened PKL further in the mail).
Then, I propose to add a new property to each property descriptor: privateKey.
When a property is read or modified somewhere in the code, the operation can
only complete if the value of
getOwnProprtyDescriptor(currentProperty).privateKey is in the PKL. It will
fails otherwhise (return undefined for a read operation or throw an error if an
attempt is made to change its value).
{
private key ModulePrivate; // generate a new private key named
ModulePrivate, and add it to the current scope’ PKL
// Create a new global property called “doSomethingPrivate” and only
accessible to scopes who have the “ModulePrivate” key
<private: ModulePrivate> function doSomethingPrivate() { ... }
// Create a new global property called “getModulePrivateKey” accessible
to every scope
function getModulePrivateKey() { return ModulePrivate; }
doSomethingPrivate(); // works
/* As the interpreter goes out of the scope where ModulePrivate is
defined, ModulePrivate is removed from the PrivateKeys collection */
}
try { doSomethingPrivate(); } catch (ex) {} // throw a “undefined is not an
object” exception as doSomethingPrivate returned ‘undefined’ (ModulePrivate is
not in the PKL)
private key ModulePrivate = getModulePrivateKey(); // private key +=
getModulePrivateKey() would works, too (in case you don’t need a reference to
the key)
try { doSomethingPrivate(); } catch (ex) {} // works
The only feature that disappeard is the ability to define more than one
property having the same “apparent” name.
I personnally feel this was a bad practice, anyway. I don’t like the fact a
property could change of name in function of the scope. And I find it even
worse that two properties sharing the same name in two different scopes can’t
share the same name in the same scope because the “property name” is become a
variable and you can’t have two variables with the same name.
To make my point clear, here an example (for the purpose of the demonstration,
I want to define a private method (clone) in the Obj class that can only be
accessed from within the own Obj instance or by a SharedClass instance, but not
within another Obj instance) :
{
private getPrivateName;
function SharedClass(a, b) {
private clone = a.getPrivateName();
private clone2 = b.getPrivateName(); // #fail: it’s the same
method, but I had to choose a different name!
this.c = a.clone();
this.d = b.clone2();
}
function Obj() {
private clone;
this.getPrivateName = function() { return #.clone; }
this.clone = function() { ... }
}
}
Using my proposal, it would be cleaner :
{
private key SharedProp;
function SharedClass(a, b) {
private key += a.getPrivateName();
private key += b.getPrivateName();
this.c = a.clone();
this.d = b.clone(); // same name
}
function Obj() {
private key ObjInstancePrivate;
this.<private: ObjInstancePrivate>clone = function() { ... }
this.<private: SharedProp>getPrivateName = function() {
return ObjInstancePrivate;
}
}
}
The problem shown before can be even worse: imagine you have to work on objects
in a loop, you can’t import all property names and you’ll be forced to use the
[] notation in your code. It’s not the case using my proposal since you can add
“anonymous” private names to the scope’ PKL.
My proposal is also simpler in the sense you don’t need to modify the fact that
a property name has to be a String. It also make runtime optimisation easier to
find out since you don’t need to know which ‘private names’ are loaded because
only one property could have the “clone” name on the object, anyway (that the
property read/write will throw an error or not hasn’t to be known at
compilation time).
Any thought on this ?
Regards,
François
From: Andrew Dupont
Sent: Sunday, March 20, 2011 6:54 AM
To: Sam Tobin-Hochstadt
Cc: [email protected]
Subject: Re: About private names
On Mar 19, 2011, at 7:02 PM, Sam Tobin-Hochstadt wrote:
> You're correct -- this won't do what you probably intended. But the
> great thing about private names is that this is a problem you can
> *locally* fix. For example:
>
> private myClone = installCloneLibrary();
> var twin = [{a:0}, {b:1}].myClone();
> var thing = MyObj.clone();
Yeah, but at that point one might as well just name the function myClone
(replacing "my" with some framework-specific prefix) and eschew private names
altogether. In this example, being able to name the method "clone" without fear
of naming collisions is the whole point.
> or
>
> var cloneProp = installCloneLibrary();
> var twin = [{a:0}, {b:1}][cloneProp]();
> var thing = MyObj.clone();
This is more palatable, but I wager it's far harder for end-users to grok.
Anyway, now that I've confirmed my suspicions, I'm hesitant about the private
names proposal as described. The fact that declaring a certain name as private
affects _all_ property name lookups in that scope (all lookups that use the dot
operator or object literal syntax, at least) — well, I'm not sure I like the
implications. It would mean a new and _surprising_ distinction between dot
notation and bracket notation.
As a maintainer of a framework that does quite a bit of built-in extension, I
can't imagine us using private names for this purpose. If we wanted to define
{}.clone in this manner, we'd be exchanging one potential collision (one
property defined in one place) for another (every property defined in the same
lexical scope). If the private names had their own operator (e.g., twin#clone
vs. twin.clone), it'd at least be worth considering.
I'm sure private names would be useful for other reasons, but IMO it wouldn't
solve the problem of safely extending built-ins.
Cheers,
Andrew
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss