Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #17918 > unrolled thread
| Started by | JJ <jaejunks@nah.meh> |
|---|---|
| First post | 2013-01-03 10:34 +0000 |
| Last post | 2013-01-04 02:33 +0000 |
| Articles | 11 — 3 participants |
Back to article view | Back to comp.lang.javascript
Source code "objectifying" technique? JJ <jaejunks@nah.meh> - 2013-01-03 10:34 +0000
Re: Source code "objectifying" technique? Stefan Weiss <krewecherl@gmail.com> - 2013-01-03 19:32 +0100
Re: Source code "objectifying" technique? JJ <jaejunks@nah.meh> - 2013-01-03 20:13 +0000
Re: Source code "objectifying" technique? Stefan Weiss <krewecherl@gmail.com> - 2013-01-03 23:57 +0100
Re: Source code "objectifying" technique? Stefan Weiss <krewecherl@gmail.com> - 2013-01-04 00:44 +0100
Re: Source code "objectifying" technique? JJ <jaejunks@nah.meh> - 2013-01-04 02:00 +0000
Re: Source code "objectifying" technique? Scott Sauyet <scott.sauyet@gmail.com> - 2013-01-03 10:37 -0800
Re: Source code "objectifying" technique? Scott Sauyet <scott.sauyet@gmail.com> - 2013-01-03 10:43 -0800
Re: Source code "objectifying" technique? JJ <jaejunks@nah.meh> - 2013-01-03 20:33 +0000
Re: Source code "objectifying" technique? Scott Sauyet <scott.sauyet@gmail.com> - 2013-01-03 13:09 -0800
Re: Source code "objectifying" technique? JJ <jaejunks@nah.meh> - 2013-01-04 02:33 +0000
| From | JJ <jaejunks@nah.meh> |
|---|---|
| Date | 2013-01-03 10:34 +0000 |
| Subject | Source code "objectifying" technique? |
| Message-ID | <XnsA13DB38A51C6jj@0.0.0.55> |
Sometimes I need some a library from the web, but its functions are all
globally defined instead of object based. For example:
var config=123;
function abc(){
//does something
}
function def(){
//does something else
}
function ghi(a){
a=a||config;
abc(def(a));
}
function jkl(a){
a=a||config;
def(a);
}
I want to put all those functions in a self contained object so that
accessing them would be like:
theLib.abc();
theLib.ghi();
theLib.abc();
theLib.abc(456);
Usually I would convert each functions including all of the references
like below.
theLib={};
theLib.config=123;
theLib.abc=function(){
return theLib.config;
}
theLib.def=function(){
return theLib.config*10;
}
theLib.ghi=function(a){
a=a||theLib.config;
theLib.abc(theLib.def(a));
}
theLib.jkl=function(a){
a=a||theLib.config;
theLib.def(a);
}
As you can see, this is a tedious work. Even for a 2KB code. Is there a
simpler way to do this?
[toc] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2013-01-03 19:32 +0100 |
| Message-ID | <kc4ir7$bh7$1@news.albasani.net> |
| In reply to | #17918 |
On 2013-01-03 11:34, JJ wrote:
> Sometimes I need some a library from the web, but its functions are all
> globally defined instead of object based. For example:
>
> var config=123;
> function abc(){
> //does something
> }
> function def(){
> //does something else
> }
> function ghi(a){
> a=a||config;
> abc(def(a));
> }
> function jkl(a){
> a=a||config;
> def(a);
> }
>
> I want to put all those functions in a self contained object so that
> accessing them would be like:
>
> theLib.abc();
> theLib.ghi();
> theLib.abc();
> theLib.abc(456);
Okay, as long as you're aware of that calling abc() is _not_ the same
thing as calling theLib.abc(). At least make sure to check if any of the
functions use |this|.
> Usually I would convert each functions including all of the references
> like below.
>
> theLib={};
> theLib.config=123;
> theLib.abc=function(){
> return theLib.config;
> }
> theLib.def=function(){
> return theLib.config*10;
> }
> theLib.ghi=function(a){
> a=a||theLib.config;
> theLib.abc(theLib.def(a));
> }
> theLib.jkl=function(a){
> a=a||theLib.config;
> theLib.def(a);
> }
>
> As you can see, this is a tedious work. Even for a 2KB code. Is there a
> simpler way to do this?
Depends on the library, but something like this might work:
var theLib = (function () {
// -- start original lib content --
var config = {...};
function abc () {...}
function def () {...} // private helper
function ghi () {...}
// -- end original lib content --
// this will be the public API of the library
return {
abc: abc,
ghi: ghi,
...
};
})();
theLib.abc(123);
Not every collection of functions can be contained in this way, but it
should work for your typical bunch-of-global-functions-because-
-the-author-doesn't-know-any-better library.
- stefan
[toc] | [prev] | [next] | [standalone]
| From | JJ <jaejunks@nah.meh> |
|---|---|
| Date | 2013-01-03 20:13 +0000 |
| Message-ID | <XnsA13E219E61C5Ejj@0.0.0.55> |
| In reply to | #17919 |
Stefan Weiss <krewecherl@gmail.com> wrote:
> Okay, as long as you're aware of that calling abc() is _not_ the same
> thing as calling theLib.abc(). At least make sure to check if any of
the
> functions use |this|.
Yes, I always watch out for any of their own objects, "this" usage and
bound functions usage. I leave them as is, if it's beyod my capability.
> Depends on the library, but something like this might work:
> ...
That'll do very nicely. Thanks. Got to get used to this.
> Not every collection of functions can be contained in this way, but it
> should work for your typical bunch-of-global-functions-because-
> -the-author-doesn't-know-any-better library.
Like bound functions?
...
Also, do this two conversions have any functionality difference? Or may
be leads to possible error elsewhere?
//original
function abc(){}
//conversion #1
theLib.abc=function abc(){};
//conversion #2
theLib.abc=function(){};
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2013-01-03 23:57 +0100 |
| Message-ID | <kc52d9$dau$1@news.albasani.net> |
| In reply to | #17922 |
On 2013-01-03 21:13, JJ wrote:
> Stefan Weiss <krewecherl@gmail.com> wrote:
>> Not every collection of functions can be contained in this way, but it
>> should work for your typical bunch-of-global-functions-because-
>> -the-author-doesn't-know-any-better library.
>
> Like bound functions?
Bound as in Function.prototype.bind? Maybe. Off the top of my head, I
can't think of how that would cause problems, if what the functions are
bound to is also in the scope of the anonymous closure.
I was thinking more of libraries directly setting properties on the
global object, or missing variable declarations.
> Also, do this two conversions have any functionality difference? Or may
> be leads to possible error elsewhere?
>
> //original
> function abc(){}
> //conversion #1
> theLib.abc=function abc(){};
> //conversion #2
> theLib.abc=function(){};
Conversion #2 has the potential to cause problems in JScript, because of
the braindead way IE handles named function expressions:
http://kangax.github.com/nfe/#jscript-bugs
This is why I generally avoid NFEs. I still want most functions to have
a name, because it makes debugging so much easier in large applications.
As a result, I often prefer function declarations over function
expressions, even if it requires the "return {...API...}" bit at the and
of a "module", like in the example from my previous post.
I do use function expressions a lot, but when I find myself writing code
like this -
button.addEventListener("click", function (evt) {
// 10 lines of code
connection.post(url, params, function (resp) {
// and maybe another nested function...
});
});
- I tend to refactor it into something simpler:
button.addEventListener("click", handleClick);
function handleClick (evt) {
// 10 lines of code
connection.post(url, params, receiveResponse);
}
function receiveResponse (resp) {
// and maybe another nested function...
}
This will give all functions a name, making debugging, documenting, and
visually scanning the code easier. It also keeps the function bodies
short and avoids the typical >-shape of highly nested functions
(callback hell).
All of that is just my personal preferred style, not a general
recommendation, but it has served me well over the years.
- stefan
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2013-01-04 00:44 +0100 |
| Message-ID | <kc5550$i9f$1@news.albasani.net> |
| In reply to | #17926 |
On 2013-01-03 23:57, Stefan Weiss wrote:
>> //conversion #1
>> theLib.abc=function abc(){};
>> //conversion #2
>> theLib.abc=function(){};
>
> Conversion #2 has the potential to cause problems in JScript
Typo - that should have read "Conversion #1".
- stefan
[toc] | [prev] | [next] | [standalone]
| From | JJ <jaejunks@nah.meh> |
|---|---|
| Date | 2013-01-04 02:00 +0000 |
| Message-ID | <XnsA13E5C583F660jj@0.0.0.55> |
| In reply to | #17926 |
Stefan Weiss <krewecherl@gmail.com> wrote: > Bound as in Function.prototype.bind? Maybe. Off the top of my head, I > can't think of how that would cause problems, if what the functions are > bound to is also in the scope of the anonymous closure. > I was thinking more of libraries directly setting properties on the > global object, or missing variable declarations. Yes, including "call" and "apply". OK. Maybe I'm just too worried. > Conversion #1[edited] has the potential to cause problems in JScript, because of > the braindead way IE handles named function expressions: > > http://kangax.github.com/nfe/#jscript-bugs Didn't know that, and that it can cause many problems. I'll keep that for reference, thanks.
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott.sauyet@gmail.com> |
|---|---|
| Date | 2013-01-03 10:37 -0800 |
| Message-ID | <efe2e252-786f-4956-8d17-237cdeb6681e@f8g2000yqa.googlegroups.com> |
| In reply to | #17918 |
JJ wrote:
> Sometimes I need some a library from the web, but its functions are all
> globally defined instead of object based. For example:
>
> var config=123;
> function abc(){
> //does something
> }
> [ ... ]
> function ghi(a){
> a=a||config;
> abc(def(a));}
> [ ... ]
> I want to put all those functions in a self contained object so that
> accessing them would be like:
>
> theLib.abc();
> theLib.ghi();
> theLib.abc(456);
>
> Usually I would convert each functions including all of the references
> like below.
>
> theLib={};
> theLib.config=123;
> theLib.abc=function(){
> return theLib.config;}
> [ ... ]
> theLib.ghi=function(a){
> a=a||theLib.config;
> theLib.abc(theLib.def(a));}
>[ ... ]
> As you can see, this is a tedious work. Even for a 2KB code. Is there a
> simpler way to do this?
My first question would be how you would distinguish between the
global variables that you do want to convert and those (possibly)
accidental ones like `a` in `ghi()` and `jkl()` above.
But if you want to pursue this, I would suggest you look at Javascript
parsers. There are a number of them written in Javascript, including
Uglify, Narcissus, Esprima, and Acorn. I'm sure you can find them all
quickly with a web search. Once you have the abstract syntax tree
representation of this code, especially if they tie all statements to
lines/columns in the code, perhaps you would be able to use this to
create a new representation that simply inserted "theLib." in all the
correct spots.
It's just a thought. I've never tried anything like this.
Best of luck,
-- Scott
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott.sauyet@gmail.com> |
|---|---|
| Date | 2013-01-03 10:43 -0800 |
| Message-ID | <f0b05c11-efed-4c03-9660-a71f26e33895@x3g2000yqo.googlegroups.com> |
| In reply to | #17920 |
Scott Sauyet wrote: > JJ wrote: >> Sometimes I need some a library from the web, but its functions are all >> globally defined instead of object based. [ ... ] >> I want to put all those functions in a self contained object [ ... ] > [ ...] I would suggest you look at Javascript parsers. Or just do as Stefan suggested. His idea is slightly less general than mine, and requires you to actually distinguish the public API you want to supply. But that's probably for the better. And it's a heck of lot simpler! -- Scott
[toc] | [prev] | [next] | [standalone]
| From | JJ <jaejunks@nah.meh> |
|---|---|
| Date | 2013-01-03 20:33 +0000 |
| Message-ID | <XnsA13E24E26DB86jj@0.0.0.55> |
| In reply to | #17920 |
Scott Sauyet <scott.sauyet@gmail.com> wrote: > My first question would be how you would distinguish between the > global variables that you do want to convert and those (possibly) > accidental ones like `a` in `ghi()` and `jkl()` above. The "a" is a function parameter. It's practically a local object of that function rather than a global object. The code are merely examples that some functions depends on their own library's variable. > But if you want to pursue this, I would suggest you look at Javascript > parsers. There are a number of them written in Javascript, including > Uglify, Narcissus, Esprima, and Acorn. I'm sure you can find them all > quickly with a web search. Once you have the abstract syntax tree > representation of this code, especially if they tie all statements to > lines/columns in the code, perhaps you would be able to use this to > create a new representation that simply inserted "theLib." in all the > correct spots. Isn't Uglify a code compressor? I do have an "uglify.js", but it's based on simple regex search+replace. It's not aware of code syntax nor context. The other three are new to me. I'll check them out. Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Scott Sauyet <scott.sauyet@gmail.com> |
|---|---|
| Date | 2013-01-03 13:09 -0800 |
| Message-ID | <3004f774-dc8d-4e87-9d3c-9f0d6f4930f8@x20g2000vbf.googlegroups.com> |
| In reply to | #17923 |
JJ wrote: > Scott Sauyet wrote: >> My first question would be how you would distinguish between the >> global variables that you do want to convert and those (possibly) >> accidental ones like `a` in `ghi()` and `jkl()` above. > > The "a" is a function parameter. It's practically a local object of that > function rather than a global object. The code are merely examples that > some functions depends on their own library's variable. So, I'm blind. So what? :-) >> But if you want to pursue this, I would suggest you look at Javascript >> parsers. There are a number of them written in Javascript, including >> Uglify, Narcissus, Esprima, and Acorn. [ ... ] > > Isn't Uglify a code compressor? I do have an "uglify.js", but it's based > on simple regex search+replace. It's not aware of code syntax nor > context. The other three are new to me. I'll check them out. Thanks. It must be a later version of Uglify that's based on creating an Abstract Syntax Tree first; I think he might have released the parser independently as well. But I wouldn't bother with that one, as the author later wrote Acorn as a better, faster, more standards-compliant parser. There's also another one I forgot to mention, called ZeParser. Good luck, -- Scott
[toc] | [prev] | [next] | [standalone]
| From | JJ <jaejunks@nah.meh> |
|---|---|
| Date | 2013-01-04 02:33 +0000 |
| Message-ID | <XnsA13E620EF9D3Fjj@0.0.0.55> |
| In reply to | #17924 |
Scott Sauyet <scott.sauyet@gmail.com> wrote: > So, I'm blind. So what? :-) Dunno... :D > It must be a later version of Uglify that's based on creating an > Abstract Syntax Tree first; I think he might have released the parser > independently as well. But I wouldn't bother with that one, as the > author later wrote Acorn as a better, faster, more standards-compliant > parser. There's also another one I forgot to mention, called > ZeParser. I rechecked my "uglify.js" with other popular uglify-ers I could find. Turned out that mine is entirely different library. A lightweight library for compression only. Figures...-_- I think I got enough libraries to check, thanks. Time for research...
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web