Even though I wrote it, I don't think the clone example on the Private Names
pages is very clear so I'll take another trying at explaining the conflict free
extension use cases. Just to make sure that we don't confuse things with any
assumptions about the implicit semantics of a clone operation I'm going to use
a method named "work" instead of "clone".
#1 A framework writer needs to add a method to object prototype. They use that
method extensive internally within the framework.They assign a private name
that they internally reference as 'work' for that method. They also provide a
way for client code to access that private name.
#2 An application developer uses the framework from #1 (let's call it MF).
They are generally unaware that MF has added an extension method to
Object.prototype:
var MF = InstallMF();
var thing = MF.getAThing(); //behind the scene calls MF's work method
#3 The application developer for their own good reasons decides to add a method
named 'work' to Object.prototype. MF internally just keeps working:
var MF = InstallMF();
Object.prototype.work = function () { ...};
var thing = MF.getAThing(); //behind the scene calls MF's work method,
still works fine
var appThing = think.work(); //class the app work method.
#4 Another framework writer has also implemented method using the private name
work. The application developer decides to add that framework to the
application. MF still works as does the apps own work method:
var MF = InstallMF();
var BF = BFLoader();
Object.prototype.work = function () { ...};
var thing = MF.getAThing(); //behind the scene calls MF's work method,
still works fine
var appThing = think.work(); //class the app work method.
var bStuff = BF.buildStuff(); //behinds the scene calls BF's work method.
#5 The application writer studies the document of the MF framework and
discovers that to accomplish some specific goal using the framework they need
to call its work method on an object. Because they are already using their own
work method on the same objects they imports MF's work private name under
another name of the apps choosing:
var MF = InstallMF();
var BF = BFLoader();
Object.prototype.work = function () { ...};
var thing = MF.getAThing(); //behind the scene calls MF's work method,
still works fine
var appThing = thing.work(); //class the app work method.
var bStuff = BF.buildStuff(); //behinds the scene calls BF's work method.
private workMF = MF.names.work;
appThing.workMF(); //Explicitly MF's work method
#6 The application writer subsequently discovers that they also need to invoke
BF's work method so they also imports BFs work private name under another
name of the apps choosing:
var MF = InstallMF();
var BF = BFLoader();
Object.prototype.work = function () { ...};
var thing = MF.getAThing(); //behind the scene calls MF's work method,
still works fine
var appThing = thing.work(); //class the app work method.
var bStuff = BF.buildStuff(); //behinds the scene calls BF's work method.
private workMF = MF.names.work;
appThing.workMF(); //Explicitly MF's work method
private workBF = BF.getExtensionMethodName("work");
appThing.workBF();
Note that it is only in scenarios #5 and #6 that any sort of explicit name
disambiguation needs to be done. There are situations where the app developer
needs to have simultaneous access to similarly named extension methods. The
disambiguation only is necessary within the local code that requires such
access and the developer can choose what ever local name assignment will be
most convenient and meaningful from the app perspective.
I have a few additional comments embedded below.
On Mar 19, 2011, at 10:54 PM, Andrew Dupont wrote:
> 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.
True, the framework could have prefixed all its internal extension methods but
that is not fool proof and all internal uses of the methods may look "ugly".
From the framework perspective, you can view private names as a prefixing
mechanism that guarantees you will never have conflicts with another frameworks
prefixing. It also allows you to internally use pleasant, readable names.
>
>> 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.
Which is one of the motivation for private names. The above formulation would
need to be used even when there wasn't a conflict and as you say, it is harder
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.
There is already a distinction between dot notation and bracket notation:
var obj = {0: "zero", foo: "foo"};
var foo = 0;
print ( obj.foo === obj[foo]); //false, really obj.foo ===obj[42]
>
> 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