Fwd: Indirect references to variables
This is a common situation, but one easily solved by object literals. Reflecting on the scope is confusing and would hurt tooling (it's essentially eval).
var mapping = {Polygon: Polygon};
var meshClass = mapping[ajaxData.className];
This is a common situation, but one easily solved by object literals. Reflecting on the scope is confusing and would hurt tooling (it's essentially eval). ```js var mapping = {Polygon: Polygon}; var meshClass = mapping[ajaxData.className]; ``` On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> wrote: > ECMAScript currently offers no clean way to "dereference" a variable in > the current scope. For instance, assume an author wishes to obtain a > reference to a class using a variable that holds its name: > > class Paintbrush{ } > > let className = "Paintbrush"; > > // Would only work in browsers, not NodeJS > console.log( window[className] ); > > // Doesn't even work in NodeJS > console.log( global[className] || this[className] ); > > A hacky workaround is to create an anonymous function that simply returns > a reference to the named variable: > > function dereference(name){ > return new Function([], "return " + name)(); > } > dereference("Paintbrush") === Paintbrush; // true > > This isn't an elegant solution, nor a preferable one. Another approach > might be to leverage `eval`, which opens up the obvious issues of > performance and security. > > Having a way of indirectly referencing another variable would fix this: > > class Paintbrush{ } > > let className = "Paintbrush"; > > let classReference = \className; > console.log(classReference === Paintbrush); // true > > Sticking a backslash before a bareword identifier creates a reference to > an object whose name matches the identifier's string value. If no such > object exists in the current scope, it simply returns `undefined`. > > I can't see this being used in everyday programs, but it would facilitate > Ajax programming considerably, where classes or functions can only be > specified by name: > > {"className":"Polygon", "vertices": [[0,0]...] } > > let meshClass = \ajaxData.className; > if(meshClass instanceof Mesh){ > new meshClass(ajaxData.vertices); > } > > > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151208/c982231d/attachment.html>
John Gardner schrieb:
ECMAScript currently offers no clean way to "dereference" a variable in the current scope.
There is one. It's called eval
.
A hacky workaround is to create an anonymous function that simply returns a reference to the named variable:
function dereference(name){ return new Function([], "return " + name)(); } dereference("Paintbrush") === Paintbrush; // true
Actually that does only work with global variables as well, quite like the property access on the global object.
Another approach might be to leverage
eval
, which opens up the obvious issues of performance and security.
And so does your proposed backslash operator.
The only difference I can see would be that you are wishing to
eval
uate only identifier references not arbitrary expressions, but
that can be trivially dealt with by testing the expression to match
the Identifer production. A regex could do that.
Neither performance nor security would be any better though.
The preferred way of what you are trying to do is to whitelist the classes you want to make available, and by naming/aliasing them explicitly. Basically
var classReference = {Paintbrush, …}[className];
var instance = new classReference();
For additional security, you might want to use an object that doesn't
inherit from Object.prototype
, or just a Map
right away.
, Bergi
John Gardner schrieb: > ECMAScript currently offers no clean way to "dereference" a variable in the > current scope. There is one. It's called `eval`. > A hacky workaround is to create an anonymous function that simply returns a > reference to the named variable: > > function dereference(name){ > return new Function([], "return " + name)(); > } > dereference("Paintbrush") === Paintbrush; // true Actually that does only work with global variables as well, quite like the property access on the global object. > Another approach > might be to leverage `eval`, which opens up the obvious issues of > performance and security. And so does your proposed backslash operator. The only difference I can see would be that you are wishing to `eval`uate only identifier references not arbitrary expressions, but *that* can be trivially dealt with by testing the expression to match the Identifer production. A regex could do that. Neither performance nor security would be any better though. The preferred way of what you are trying to do is to whitelist the classes you want to make available, and by naming/aliasing them explicitly. Basically var classReference = {Paintbrush, …}[className]; var instance = new classReference(); For additional security, you might want to use an object that doesn't inherit from `Object.prototype`, or just a `Map` right away. Regards, Bergi
Trouble is, if one has literally hundreds of classes or functions that need to be matched, they'd rather not pool them all into one massive object literal for the sake of easier mapping. DRY principle fully relevant.
Also, yes, while it would be a pain for static type analysis, it wouldn't
necessarily be the same as eval
. Eval executes arbitrary code, whereas
the indirect references would only point to modifiers only:
var className = \"doSomethingSinister(/etc/passwd/);"
That line would literally be looking for a property in the current scope that'd be named this:
global["doSomethingSinister(/etc/passwd/);"]
window["doSomethingSinister(/etc/passwd/);"]
Trouble is, if one has literally hundreds of classes or functions that need to be matched, they'd rather not pool them all into one massive object literal for the sake of easier mapping. DRY principle fully relevant. Also, yes, while it would be a pain for static type analysis, it wouldn't necessarily be the same as `eval`. Eval executes arbitrary code, whereas the indirect references would only point to modifiers only: var className = \"doSomethingSinister(/etc/passwd/);" That line would literally be looking for a property in the current scope that'd be named this: global["doSomethingSinister(/etc/passwd/);"] window["doSomethingSinister(/etc/passwd/);"] On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> wrote: > This is a common situation, but one easily solved by object literals. > Reflecting on the scope is confusing and would hurt tooling (it's > essentially eval). > > ```js > var mapping = {Polygon: Polygon}; > var meshClass = mapping[ajaxData.className]; > ``` > > > > > On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> > wrote: > >> ECMAScript currently offers no clean way to "dereference" a variable in >> the current scope. For instance, assume an author wishes to obtain a >> reference to a class using a variable that holds its name: >> >> class Paintbrush{ } >> >> let className = "Paintbrush"; >> >> // Would only work in browsers, not NodeJS >> console.log( window[className] ); >> >> // Doesn't even work in NodeJS >> console.log( global[className] || this[className] ); >> >> A hacky workaround is to create an anonymous function that simply returns >> a reference to the named variable: >> >> function dereference(name){ >> return new Function([], "return " + name)(); >> } >> dereference("Paintbrush") === Paintbrush; // true >> >> This isn't an elegant solution, nor a preferable one. Another approach >> might be to leverage `eval`, which opens up the obvious issues of >> performance and security. >> >> Having a way of indirectly referencing another variable would fix this: >> >> class Paintbrush{ } >> >> let className = "Paintbrush"; >> >> let classReference = \className; >> console.log(classReference === Paintbrush); // true >> >> Sticking a backslash before a bareword identifier creates a reference to >> an object whose name matches the identifier's string value. If no such >> object exists in the current scope, it simply returns `undefined`. >> >> I can't see this being used in everyday programs, but it would facilitate >> Ajax programming considerably, where classes or functions can only be >> specified by name: >> >> {"className":"Polygon", "vertices": [[0,0]...] } >> >> let meshClass = \ajaxData.className; >> if(meshClass instanceof Mesh){ >> new meshClass(ajaxData.vertices); >> } >> >> >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151209/713ea1fc/attachment-0001.html>
Are you putting hundreds of classes into a single scope?
Are you putting hundreds of classes into a single scope? On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> wrote: > Trouble is, if one has literally hundreds of classes or functions that > need to be matched, they'd rather not pool them all into one massive object > literal for the sake of easier mapping. DRY principle fully relevant. > > Also, yes, while it would be a pain for static type analysis, it wouldn't > necessarily be the same as `eval`. Eval executes arbitrary code, whereas > the indirect references would only point to modifiers only: > > var className = \"doSomethingSinister(/etc/passwd/);" > > That line would literally be looking for a property in the current scope > that'd be named this: > > global["doSomethingSinister(/etc/passwd/);"] > window["doSomethingSinister(/etc/passwd/);"] > > > > On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> > wrote: > >> This is a common situation, but one easily solved by object literals. >> Reflecting on the scope is confusing and would hurt tooling (it's >> essentially eval). >> >> ```js >> var mapping = {Polygon: Polygon}; >> var meshClass = mapping[ajaxData.className]; >> ``` >> >> >> >> >> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >> wrote: >> >>> ECMAScript currently offers no clean way to "dereference" a variable in >>> the current scope. For instance, assume an author wishes to obtain a >>> reference to a class using a variable that holds its name: >>> >>> class Paintbrush{ } >>> >>> let className = "Paintbrush"; >>> >>> // Would only work in browsers, not NodeJS >>> console.log( window[className] ); >>> >>> // Doesn't even work in NodeJS >>> console.log( global[className] || this[className] ); >>> >>> A hacky workaround is to create an anonymous function that simply >>> returns a reference to the named variable: >>> >>> function dereference(name){ >>> return new Function([], "return " + name)(); >>> } >>> dereference("Paintbrush") === Paintbrush; // true >>> >>> This isn't an elegant solution, nor a preferable one. Another approach >>> might be to leverage `eval`, which opens up the obvious issues of >>> performance and security. >>> >>> Having a way of indirectly referencing another variable would fix this: >>> >>> class Paintbrush{ } >>> >>> let className = "Paintbrush"; >>> >>> let classReference = \className; >>> console.log(classReference === Paintbrush); // true >>> >>> Sticking a backslash before a bareword identifier creates a reference to >>> an object whose name matches the identifier's string value. If no such >>> object exists in the current scope, it simply returns `undefined`. >>> >>> I can't see this being used in everyday programs, but it would >>> facilitate Ajax programming considerably, where classes or functions can >>> only be specified by name: >>> >>> {"className":"Polygon", "vertices": [[0,0]...] } >>> >>> let meshClass = \ajaxData.className; >>> if(meshClass instanceof Mesh){ >>> new meshClass(ajaxData.vertices); >>> } >>> >>> >>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151209/d7be7d60/attachment.html>
Only at top-level. This issue actually surfaced when I realised I had no way to indirectly access classes by name... and for some reason, neither the global object nor the eval hack were returning anything. It worked fine for simple variables, so I wondered if that was an intentional side-effect of classes in ECMAScript.
(Of course, if not, it may actually be an issue with V8's implementation...)
Only at top-level. This issue actually surfaced when I realised I had no way to indirectly access classes by name... and for some reason, neither the global object nor the eval hack were returning anything. It worked fine for simple variables, so I wondered if that was an intentional side-effect of classes in ECMAScript. (Of course, if not, it may actually be an issue with V8's implementation...) On 09/12/2015 5:05 PM, "Bradley Meck" <bradley.meck at gmail.com> wrote: > Are you putting hundreds of classes into a single scope? > > On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> > wrote: > >> Trouble is, if one has literally hundreds of classes or functions that >> need to be matched, they'd rather not pool them all into one massive object >> literal for the sake of easier mapping. DRY principle fully relevant. >> >> Also, yes, while it would be a pain for static type analysis, it wouldn't >> necessarily be the same as `eval`. Eval executes arbitrary code, whereas >> the indirect references would only point to modifiers only: >> >> var className = \"doSomethingSinister(/etc/passwd/);" >> >> That line would literally be looking for a property in the current scope >> that'd be named this: >> >> global["doSomethingSinister(/etc/passwd/);"] >> window["doSomethingSinister(/etc/passwd/);"] >> >> >> >> On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> >> wrote: >> >>> This is a common situation, but one easily solved by object literals. >>> Reflecting on the scope is confusing and would hurt tooling (it's >>> essentially eval). >>> >>> ```js >>> var mapping = {Polygon: Polygon}; >>> var meshClass = mapping[ajaxData.className]; >>> ``` >>> >>> >>> >>> >>> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >>> wrote: >>> >>>> ECMAScript currently offers no clean way to "dereference" a variable in >>>> the current scope. For instance, assume an author wishes to obtain a >>>> reference to a class using a variable that holds its name: >>>> >>>> class Paintbrush{ } >>>> >>>> let className = "Paintbrush"; >>>> >>>> // Would only work in browsers, not NodeJS >>>> console.log( window[className] ); >>>> >>>> // Doesn't even work in NodeJS >>>> console.log( global[className] || this[className] ); >>>> >>>> A hacky workaround is to create an anonymous function that simply >>>> returns a reference to the named variable: >>>> >>>> function dereference(name){ >>>> return new Function([], "return " + name)(); >>>> } >>>> dereference("Paintbrush") === Paintbrush; // true >>>> >>>> This isn't an elegant solution, nor a preferable one. Another approach >>>> might be to leverage `eval`, which opens up the obvious issues of >>>> performance and security. >>>> >>>> Having a way of indirectly referencing another variable would fix this: >>>> >>>> class Paintbrush{ } >>>> >>>> let className = "Paintbrush"; >>>> >>>> let classReference = \className; >>>> console.log(classReference === Paintbrush); // true >>>> >>>> Sticking a backslash before a bareword identifier creates a reference >>>> to an object whose name matches the identifier's string value. If no such >>>> object exists in the current scope, it simply returns `undefined`. >>>> >>>> I can't see this being used in everyday programs, but it would >>>> facilitate Ajax programming considerably, where classes or functions can >>>> only be specified by name: >>>> >>>> {"className":"Polygon", "vertices": [[0,0]...] } >>>> >>>> let meshClass = \ajaxData.className; >>>> if(meshClass instanceof Mesh){ >>>> new meshClass(ajaxData.vertices); >>>> } >>>> >>>> >>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151209/09395c87/attachment-0001.html>
Can you not put each class in its own module, and simply require, by name, the one you want?
Can you not put each class in its own module, and simply require, by name, the one you want? On Tue, Dec 8, 2015 at 10:19 PM, John Gardner <gardnerjohng at gmail.com> wrote: > Only at top-level. This issue actually surfaced when I realised I had no > way to indirectly access classes by name... and for some reason, neither > the global object nor the eval hack were returning anything. It worked fine > for simple variables, so I wondered if that was an intentional side-effect > of classes in ECMAScript. > > (Of course, if not, it may actually be an issue with V8's > implementation...) > On 09/12/2015 5:05 PM, "Bradley Meck" <bradley.meck at gmail.com> wrote: > >> Are you putting hundreds of classes into a single scope? >> >> On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> >> wrote: >> >>> Trouble is, if one has literally hundreds of classes or functions that >>> need to be matched, they'd rather not pool them all into one massive object >>> literal for the sake of easier mapping. DRY principle fully relevant. >>> >>> Also, yes, while it would be a pain for static type analysis, it >>> wouldn't necessarily be the same as `eval`. Eval executes arbitrary code, >>> whereas the indirect references would only point to modifiers only: >>> >>> var className = \"doSomethingSinister(/etc/passwd/);" >>> >>> That line would literally be looking for a property in the current scope >>> that'd be named this: >>> >>> global["doSomethingSinister(/etc/passwd/);"] >>> window["doSomethingSinister(/etc/passwd/);"] >>> >>> >>> >>> On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> >>> wrote: >>> >>>> This is a common situation, but one easily solved by object literals. >>>> Reflecting on the scope is confusing and would hurt tooling (it's >>>> essentially eval). >>>> >>>> ```js >>>> var mapping = {Polygon: Polygon}; >>>> var meshClass = mapping[ajaxData.className]; >>>> ``` >>>> >>>> >>>> >>>> >>>> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >>>> wrote: >>>> >>>>> ECMAScript currently offers no clean way to "dereference" a variable >>>>> in the current scope. For instance, assume an author wishes to obtain a >>>>> reference to a class using a variable that holds its name: >>>>> >>>>> class Paintbrush{ } >>>>> >>>>> let className = "Paintbrush"; >>>>> >>>>> // Would only work in browsers, not NodeJS >>>>> console.log( window[className] ); >>>>> >>>>> // Doesn't even work in NodeJS >>>>> console.log( global[className] || this[className] ); >>>>> >>>>> A hacky workaround is to create an anonymous function that simply >>>>> returns a reference to the named variable: >>>>> >>>>> function dereference(name){ >>>>> return new Function([], "return " + name)(); >>>>> } >>>>> dereference("Paintbrush") === Paintbrush; // true >>>>> >>>>> This isn't an elegant solution, nor a preferable one. Another approach >>>>> might be to leverage `eval`, which opens up the obvious issues of >>>>> performance and security. >>>>> >>>>> Having a way of indirectly referencing another variable would fix this: >>>>> >>>>> class Paintbrush{ } >>>>> >>>>> let className = "Paintbrush"; >>>>> >>>>> let classReference = \className; >>>>> console.log(classReference === Paintbrush); // true >>>>> >>>>> Sticking a backslash before a bareword identifier creates a reference >>>>> to an object whose name matches the identifier's string value. If no such >>>>> object exists in the current scope, it simply returns `undefined`. >>>>> >>>>> I can't see this being used in everyday programs, but it would >>>>> facilitate Ajax programming considerably, where classes or functions can >>>>> only be specified by name: >>>>> >>>>> {"className":"Polygon", "vertices": [[0,0]...] } >>>>> >>>>> let meshClass = \ajaxData.className; >>>>> if(meshClass instanceof Mesh){ >>>>> new meshClass(ajaxData.vertices); >>>>> } >>>>> >>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss at mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151208/e804e436/attachment.html>
Never mind. This is beginning to south like too much of a damn edge case for it to be of language-wide relevance.
Pretend this discussion never happened.
Never mind. This is beginning to south like too much of a damn edge case for it to be of language-wide relevance. Pretend this discussion never happened. On 09/12/2015 5:40 PM, "Jordan Harband" <ljharb at gmail.com> wrote: > Can you not put each class in its own module, and simply require, by name, > the one you want? > > On Tue, Dec 8, 2015 at 10:19 PM, John Gardner <gardnerjohng at gmail.com> > wrote: > >> Only at top-level. This issue actually surfaced when I realised I had no >> way to indirectly access classes by name... and for some reason, neither >> the global object nor the eval hack were returning anything. It worked fine >> for simple variables, so I wondered if that was an intentional side-effect >> of classes in ECMAScript. >> >> (Of course, if not, it may actually be an issue with V8's >> implementation...) >> On 09/12/2015 5:05 PM, "Bradley Meck" <bradley.meck at gmail.com> wrote: >> >>> Are you putting hundreds of classes into a single scope? >>> >>> On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> >>> wrote: >>> >>>> Trouble is, if one has literally hundreds of classes or functions that >>>> need to be matched, they'd rather not pool them all into one massive object >>>> literal for the sake of easier mapping. DRY principle fully relevant. >>>> >>>> Also, yes, while it would be a pain for static type analysis, it >>>> wouldn't necessarily be the same as `eval`. Eval executes arbitrary code, >>>> whereas the indirect references would only point to modifiers only: >>>> >>>> var className = \"doSomethingSinister(/etc/passwd/);" >>>> >>>> That line would literally be looking for a property in the current >>>> scope that'd be named this: >>>> >>>> global["doSomethingSinister(/etc/passwd/);"] >>>> window["doSomethingSinister(/etc/passwd/);"] >>>> >>>> >>>> >>>> On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> >>>> wrote: >>>> >>>>> This is a common situation, but one easily solved by object literals. >>>>> Reflecting on the scope is confusing and would hurt tooling (it's >>>>> essentially eval). >>>>> >>>>> ```js >>>>> var mapping = {Polygon: Polygon}; >>>>> var meshClass = mapping[ajaxData.className]; >>>>> ``` >>>>> >>>>> >>>>> >>>>> >>>>> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >>>>> wrote: >>>>> >>>>>> ECMAScript currently offers no clean way to "dereference" a variable >>>>>> in the current scope. For instance, assume an author wishes to obtain a >>>>>> reference to a class using a variable that holds its name: >>>>>> >>>>>> class Paintbrush{ } >>>>>> >>>>>> let className = "Paintbrush"; >>>>>> >>>>>> // Would only work in browsers, not NodeJS >>>>>> console.log( window[className] ); >>>>>> >>>>>> // Doesn't even work in NodeJS >>>>>> console.log( global[className] || this[className] ); >>>>>> >>>>>> A hacky workaround is to create an anonymous function that simply >>>>>> returns a reference to the named variable: >>>>>> >>>>>> function dereference(name){ >>>>>> return new Function([], "return " + name)(); >>>>>> } >>>>>> dereference("Paintbrush") === Paintbrush; // true >>>>>> >>>>>> This isn't an elegant solution, nor a preferable one. Another >>>>>> approach might be to leverage `eval`, which opens up the obvious issues of >>>>>> performance and security. >>>>>> >>>>>> Having a way of indirectly referencing another variable would fix >>>>>> this: >>>>>> >>>>>> class Paintbrush{ } >>>>>> >>>>>> let className = "Paintbrush"; >>>>>> >>>>>> let classReference = \className; >>>>>> console.log(classReference === Paintbrush); // true >>>>>> >>>>>> Sticking a backslash before a bareword identifier creates a reference >>>>>> to an object whose name matches the identifier's string value. If no such >>>>>> object exists in the current scope, it simply returns `undefined`. >>>>>> >>>>>> I can't see this being used in everyday programs, but it would >>>>>> facilitate Ajax programming considerably, where classes or functions can >>>>>> only be specified by name: >>>>>> >>>>>> {"className":"Polygon", "vertices": [[0,0]...] } >>>>>> >>>>>> let meshClass = \ajaxData.className; >>>>>> if(meshClass instanceof Mesh){ >>>>>> new meshClass(ajaxData.vertices); >>>>>> } >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> es-discuss mailing list >>>>>> es-discuss at mozilla.org >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151209/9b7c1c3b/attachment-0001.html>
You're probably better off building some sort of class map into your application to handle this.
Either
A) You have all your classes loaded in one scope, you can have a map of strings to those classes which a method can retrieve and instantiate. Drawback is that your method (and the map) needs to also be defined in the same scope.
or
B) You don't have all classes in scope and are loading them dynamically (with something like requirejs), in which case your function needs a class-map of class names to paths, which your loader can pull in for you and asynchronously create. I tend towards using a service manager pattern to do this in applications where I have a requirement.
In the second instance you could introduce a compile step to create your class map. Very much dependent on your workflow. Regardless of how you're loading your classes or how you're scoping your code, some sort of class map is the solution.
The only case I can think of where loading by string really becomes an issue is with ES6 modules, which AFAIK, being static would need to all be loaded at the top of the module where you're de-serializing your classes.
When ES6 modules start landing in browsers I'll be tending even more strongly towards the service manager pattern: One known place to resolve instances and factories for classes.
,
Robin Cafolla
You're probably better off building some sort of class map into your application to handle this. Either A) You have all your classes loaded in one scope, you can have a map of strings to those classes which a method can retrieve and instantiate. Drawback is that your method (and the map) needs to also be defined in the same scope. or B) You don't have all classes in scope and are loading them dynamically (with something like requirejs), in which case your function needs a class-map of class names to paths, which your loader can pull in for you and asynchronously create. I tend towards using a service manager pattern to do this in applications where I have a requirement. In the second instance you could introduce a compile step to create your class map. Very much dependent on your workflow. Regardless of how you're loading your classes or how you're scoping your code, some sort of class map is the solution. The only case I can think of where loading by string really becomes an issue is with ES6 modules, which AFAIK, being static would need to all be loaded at the top of the module where you're de-serializing your classes. When ES6 modules start landing in browsers I'll be tending even more strongly towards the service manager pattern: One known place to resolve instances and factories for classes. Regards, Robin Cafolla On 9 December 2015 at 08:46, <es-discuss-request at mozilla.org> wrote: > Send es-discuss mailing list submissions to > es-discuss at mozilla.org > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.mozilla.org/listinfo/es-discuss > or, via email, send a message with subject or body 'help' to > es-discuss-request at mozilla.org > > You can reach the person managing the list at > es-discuss-owner at mozilla.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of es-discuss digest..." > > Today's Topics: > > 1. Re: Indirect references to variables (Jordan Harband) > 2. Re: Indirect references to variables (John Gardner) > > > ---------- Forwarded message ---------- > From: Jordan Harband <ljharb at gmail.com> > To: John Gardner <gardnerjohng at gmail.com> > Cc: es-discuss <es-discuss at mozilla.org> > Date: Tue, 8 Dec 2015 22:39:51 -0800 > Subject: Re: Indirect references to variables > Can you not put each class in its own module, and simply require, by name, > the one you want? > > On Tue, Dec 8, 2015 at 10:19 PM, John Gardner <gardnerjohng at gmail.com> > wrote: > >> Only at top-level. This issue actually surfaced when I realised I had no >> way to indirectly access classes by name... and for some reason, neither >> the global object nor the eval hack were returning anything. It worked fine >> for simple variables, so I wondered if that was an intentional side-effect >> of classes in ECMAScript. >> >> (Of course, if not, it may actually be an issue with V8's >> implementation...) >> On 09/12/2015 5:05 PM, "Bradley Meck" <bradley.meck at gmail.com> wrote: >> >>> Are you putting hundreds of classes into a single scope? >>> >>> On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> >>> wrote: >>> >>>> Trouble is, if one has literally hundreds of classes or functions that >>>> need to be matched, they'd rather not pool them all into one massive object >>>> literal for the sake of easier mapping. DRY principle fully relevant. >>>> >>>> Also, yes, while it would be a pain for static type analysis, it >>>> wouldn't necessarily be the same as `eval`. Eval executes arbitrary code, >>>> whereas the indirect references would only point to modifiers only: >>>> >>>> var className = \"doSomethingSinister(/etc/passwd/);" >>>> >>>> That line would literally be looking for a property in the current >>>> scope that'd be named this: >>>> >>>> global["doSomethingSinister(/etc/passwd/);"] >>>> window["doSomethingSinister(/etc/passwd/);"] >>>> >>>> >>>> >>>> On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> >>>> wrote: >>>> >>>>> This is a common situation, but one easily solved by object literals. >>>>> Reflecting on the scope is confusing and would hurt tooling (it's >>>>> essentially eval). >>>>> >>>>> ```js >>>>> var mapping = {Polygon: Polygon}; >>>>> var meshClass = mapping[ajaxData.className]; >>>>> ``` >>>>> >>>>> >>>>> >>>>> >>>>> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >>>>> wrote: >>>>> >>>>>> ECMAScript currently offers no clean way to "dereference" a variable >>>>>> in the current scope. For instance, assume an author wishes to obtain a >>>>>> reference to a class using a variable that holds its name: >>>>>> >>>>>> class Paintbrush{ } >>>>>> >>>>>> let className = "Paintbrush"; >>>>>> >>>>>> // Would only work in browsers, not NodeJS >>>>>> console.log( window[className] ); >>>>>> >>>>>> // Doesn't even work in NodeJS >>>>>> console.log( global[className] || this[className] ); >>>>>> >>>>>> A hacky workaround is to create an anonymous function that simply >>>>>> returns a reference to the named variable: >>>>>> >>>>>> function dereference(name){ >>>>>> return new Function([], "return " + name)(); >>>>>> } >>>>>> dereference("Paintbrush") === Paintbrush; // true >>>>>> >>>>>> This isn't an elegant solution, nor a preferable one. Another >>>>>> approach might be to leverage `eval`, which opens up the obvious issues of >>>>>> performance and security. >>>>>> >>>>>> Having a way of indirectly referencing another variable would fix >>>>>> this: >>>>>> >>>>>> class Paintbrush{ } >>>>>> >>>>>> let className = "Paintbrush"; >>>>>> >>>>>> let classReference = \className; >>>>>> console.log(classReference === Paintbrush); // true >>>>>> >>>>>> Sticking a backslash before a bareword identifier creates a reference >>>>>> to an object whose name matches the identifier's string value. If no such >>>>>> object exists in the current scope, it simply returns `undefined`. >>>>>> >>>>>> I can't see this being used in everyday programs, but it would >>>>>> facilitate Ajax programming considerably, where classes or functions can >>>>>> only be specified by name: >>>>>> >>>>>> {"className":"Polygon", "vertices": [[0,0]...] } >>>>>> >>>>>> let meshClass = \ajaxData.className; >>>>>> if(meshClass instanceof Mesh){ >>>>>> new meshClass(ajaxData.vertices); >>>>>> } >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> es-discuss mailing list >>>>>> es-discuss at mozilla.org >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > > ---------- Forwarded message ---------- > From: John Gardner <gardnerjohng at gmail.com> > To: Jordan Harband <ljharb at gmail.com> > Cc: es-discuss <es-discuss at mozilla.org> > Date: Wed, 9 Dec 2015 17:46:26 +1100 > Subject: Re: Indirect references to variables > > Never mind. This is beginning to south like too much of a damn edge case > for it to be of language-wide relevance. > > Pretend this discussion never happened. > On 09/12/2015 5:40 PM, "Jordan Harband" <ljharb at gmail.com> wrote: > >> Can you not put each class in its own module, and simply require, by >> name, the one you want? >> >> On Tue, Dec 8, 2015 at 10:19 PM, John Gardner <gardnerjohng at gmail.com> >> wrote: >> >>> Only at top-level. This issue actually surfaced when I realised I had no >>> way to indirectly access classes by name... and for some reason, neither >>> the global object nor the eval hack were returning anything. It worked fine >>> for simple variables, so I wondered if that was an intentional side-effect >>> of classes in ECMAScript. >>> >>> (Of course, if not, it may actually be an issue with V8's >>> implementation...) >>> On 09/12/2015 5:05 PM, "Bradley Meck" <bradley.meck at gmail.com> wrote: >>> >>>> Are you putting hundreds of classes into a single scope? >>>> >>>> On Tue, Dec 8, 2015 at 11:56 PM, John Gardner <gardnerjohng at gmail.com> >>>> wrote: >>>> >>>>> Trouble is, if one has literally hundreds of classes or functions that >>>>> need to be matched, they'd rather not pool them all into one massive object >>>>> literal for the sake of easier mapping. DRY principle fully relevant. >>>>> >>>>> Also, yes, while it would be a pain for static type analysis, it >>>>> wouldn't necessarily be the same as `eval`. Eval executes arbitrary code, >>>>> whereas the indirect references would only point to modifiers only: >>>>> >>>>> var className = \"doSomethingSinister(/etc/passwd/);" >>>>> >>>>> That line would literally be looking for a property in the current >>>>> scope that'd be named this: >>>>> >>>>> global["doSomethingSinister(/etc/passwd/);"] >>>>> window["doSomethingSinister(/etc/passwd/);"] >>>>> >>>>> >>>>> >>>>> On 9 December 2015 at 16:09, Frankie Bagnardi <f.bagnardi at gmail.com> >>>>> wrote: >>>>> >>>>>> This is a common situation, but one easily solved by object literals. >>>>>> Reflecting on the scope is confusing and would hurt tooling (it's >>>>>> essentially eval). >>>>>> >>>>>> ```js >>>>>> var mapping = {Polygon: Polygon}; >>>>>> var meshClass = mapping[ajaxData.className]; >>>>>> ``` >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Tue, Dec 8, 2015 at 9:53 PM, John Gardner <gardnerjohng at gmail.com> >>>>>> wrote: >>>>>> >>>>>>> ECMAScript currently offers no clean way to "dereference" a variable >>>>>>> in the current scope. For instance, assume an author wishes to obtain a >>>>>>> reference to a class using a variable that holds its name: >>>>>>> >>>>>>> class Paintbrush{ } >>>>>>> >>>>>>> let className = "Paintbrush"; >>>>>>> >>>>>>> // Would only work in browsers, not NodeJS >>>>>>> console.log( window[className] ); >>>>>>> >>>>>>> // Doesn't even work in NodeJS >>>>>>> console.log( global[className] || this[className] ); >>>>>>> >>>>>>> A hacky workaround is to create an anonymous function that simply >>>>>>> returns a reference to the named variable: >>>>>>> >>>>>>> function dereference(name){ >>>>>>> return new Function([], "return " + name)(); >>>>>>> } >>>>>>> dereference("Paintbrush") === Paintbrush; // true >>>>>>> >>>>>>> This isn't an elegant solution, nor a preferable one. Another >>>>>>> approach might be to leverage `eval`, which opens up the obvious issues of >>>>>>> performance and security. >>>>>>> >>>>>>> Having a way of indirectly referencing another variable would fix >>>>>>> this: >>>>>>> >>>>>>> class Paintbrush{ } >>>>>>> >>>>>>> let className = "Paintbrush"; >>>>>>> >>>>>>> let classReference = \className; >>>>>>> console.log(classReference === Paintbrush); // true >>>>>>> >>>>>>> Sticking a backslash before a bareword identifier creates a >>>>>>> reference to an object whose name matches the identifier's string value. If >>>>>>> no such object exists in the current scope, it simply returns `undefined`. >>>>>>> >>>>>>> I can't see this being used in everyday programs, but it would >>>>>>> facilitate Ajax programming considerably, where classes or functions can >>>>>>> only be specified by name: >>>>>>> >>>>>>> {"className":"Polygon", "vertices": [[0,0]...] } >>>>>>> >>>>>>> let meshClass = \ajaxData.className; >>>>>>> if(meshClass instanceof Mesh){ >>>>>>> new meshClass(ajaxData.vertices); >>>>>>> } >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> es-discuss mailing list >>>>>>> es-discuss at mozilla.org >>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>> >>>>>>> >>>>>> >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss at mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151209/3691e5c6/attachment-0001.html>
ECMAScript currently offers no clean way to "dereference" a variable in the current scope. For instance, assume an author wishes to obtain a reference to a class using a variable that holds its name:
A hacky workaround is to create an anonymous function that simply returns a reference to the named variable:
This isn't an elegant solution, nor a preferable one. Another approach might be to leverage
eval
, which opens up the obvious issues of performance and security.Having a way of indirectly referencing another variable would fix this:
Sticking a backslash before a bareword identifier creates a reference to an object whose name matches the identifier's string value. If no such object exists in the current scope, it simply returns
undefined
.I can't see this being used in everyday programs, but it would facilitate Ajax programming considerably, where classes or functions can only be specified by name: