homepage Welcome to WebmasterWorld Guest from 54.204.94.228
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
Anonymous library loader?
Mysterious code found in the wild.
MarkFilipak

5+ Year Member



 
Msg#: 3604898 posted 5:04 am on Mar 19, 2008 (gmt 0)

When I write a library, I create an object that contains my constants, variables, and methods
like myLib.js
myLib = { thingie: ..., ... }

which I then load like this
<script type="text/javascript" src="myLib.js"></script>

Lately I'm running across stuff
that loads normally like this
<script type="text/javascript" src="myLib.js"></script>

but which contains stuff like this
(function(myLib){ myLib.thingie = ...; ... })(window);

My Comments:

Re: (function(myLib){ myLib.thingie = ...; ... })
I would say that this instantiates and executes an anonymous function.
1 - How the variable myLib gets passed in is a mystery to me.
2 - I've been lurking on the ECMAScript4 forum and from what I've gathered there, such a construction is frowned upon for scoping reasons, but cannot be made illegal because it has become so wide spread.

Re: (window)
To me, this is just plain mystifying: An anonymous function is immediately followed by a group that contains a single object which is the global object.

Got any ideas what this is about?
Why would anyone do this?
Why don't browsers barf on the
(window) part?
(Why is this giving me the creeps?)

 

mehh

5+ Year Member



 
Msg#: 3604898 posted 6:43 pm on Mar 19, 2008 (gmt 0)

I would say that this instantiates and executes an anonymous function.

This just instigates the function, the
(window) part executes it, which is how the myLib variable gets passed. I personaly cannot see why you would need to do this, the first method works just fine.
MarkFilipak

5+ Year Member



 
Msg#: 3604898 posted 12:50 am on Mar 20, 2008 (gmt 0)

Thanks, mehh,

Can you amplify or elucidate your reply please. I'm sincerely in knowledge-distress about this.

I don't see how
(function(myLib){ myLib.thingie = ...; ... })(window);
works and I'd like to take it one step at a time, parsing and interpreting. Perhaps in the process of analyzing it, I'll answer my own questions.

1
function(myLib){ myLib.thingie = ...; ... }
Stated loosely and skipping the details, this produces a value which is a functionObject and gives to it a scope chain that consists of, in this case, a single object: the globalObject (i.e., the execution context of the HTML script-element).

Comment: The function body containing expressions like this: myLib.thingie = ...; ..., is compiled. Since myLib is not declared local to the function, the scope chain is traversed seeking a variable named 'myLib'. It is not found, so a global variable is created. Also, since no variable is subsequently assigned the value of the functionObject, the function remains anonymous.

2
( Expression )
Parentheses, as a pair of tokens, act as a Grouping Operator which, in this case, returns result 1 without applying GetValue to it - adapted from: ECMA-262, section 11.1.6.

Comment: I'm unsure what it means to evaluate something without applying GetValue but the implication appears to be twofold: that the result may be of type Reference (a memory address) rather than a value (memory contents), and that no additional error checking is done while producing the result.

3
(window)
This is another group that contains the single variable: window, that returns its value: the globalObject.

4
functionObject globalObject ;
This, I think, is the result of the substitutions above. It seems like a very strange construction to me. I have no idea what it is all about and how the execution unit deals with it.

Questions:
1: In 1, how does the function compiler know that myLib is to be an object rather than just throwing an exception when "myLib.thingie" is encountered?
2: In 1, if myLib is forced to be a global object, what purpose is served by having myLib as a calling argument? - I could speculate or make a surmise but I'd like to know what actually happens at the memory alloc. level. Is this (non-existent) argument necessary?
3: In 1, since the
functionObject is anonymous, what happens to it when the current line ends? Is the memory freed or does this lead to a memory leak?
4: In 2, the Grouping Operator (parentheses) seems to do nothing. Does it somehow suppress the exception that would otherwise be thrown by this illegal construction?
5: In 3, again, Grouping Operator seems to do nothing - this time, without any imaginable utility.
6: In 4, what does this construction do?

Achernar

5+ Year Member



 
Msg#: 3604898 posted 11:43 am on Mar 20, 2008 (gmt 0)

The syntax
(function(){someJScode...})()
(function(a,b,c){someJScode...})(e,f,g)
defines and execute the function immediately.
It is similar to the syntax:
function Z(a,b,c){someJScode...}; Z(e,f,g);

The advantage is that the "anonymous" function is not available in the global scope. It can be used to initialize your library without polluting the global scope with functions and/or variable that have no use past the initialization phase.

Standard method:
var a,b,c;
a=document.getElementById('A');

function Z(i) {
do something with i
}
Z(a);

Since Z() is in the global scope, it will be available afterwards, and a page using your script can call it more than once.

anonymous function:
(function(){
var a,b,c;
a=document.getElementById('A');

function Z(i) {
do something with i
}
Z(a);
})()


Variables and functions declared within are private.

MarkFilipak

5+ Year Member



 
Msg#: 3604898 posted 7:00 pm on Mar 20, 2008 (gmt 0)

> It can be used to initialize your library without polluting...
An excellent explanation. Makes sense too. Thanks, Achernar. Do you have any insight regarding why the ECMAScript architects (working on ECMAScript4) deem such a construct to be bad practice almost to the point of JavaScript-heresy?

It occurred to me (while dreaming last night!) that in (function(myLib){ myLib.thingie = ...; ... })(window);, the role of (window); is as part of a call to the anonymous function to pass in the globalObject. So my line of code
(function(myLib){ myLib.thingie = ..., ... })(window);
really aught to be
(function(globalObject){ globalObject.myLib = {thingie : ..., ... }})(window);
What do you think?
This makes a lot more sense than what I was thinking: That
functionObject globalObject; somehow concatenated two objects and then did something mysterious with the result (which was the part that put me in such knowledge-distress).

Mystery solved. Thanks much!

Edit: Added answers.

Answers:
1: In 1, how does the function compiler know that myLib is to be an object rather than just throwing an exception when "myLib.thingie" is encountered?
Ans: The function compiler doesn't make any such assumption, and it would throw an exception if I had
myLib.myObj.thingie but doesn't for myLib.thingie because it uses myLib as the caller's argument (which, in this case, is the globalObject).
2: In 1, if myLib is forced to be a global object, what purpose is served by having myLib as a calling argument? - I could speculate or make a surmise but I'd like to know what actually happens at the memory alloc.
level. Is this (non-existent) argument necessary?
Ans: See 1, above.
3: In 1, since the functionObject is anonymous, what happens to it when the current line ends? Is the memory freed or does this lead to a memory leak?
Ans: Not answered - subject for experimentation and testing.
4: In 2, the Grouping Operator (parentheses) seems to do nothing. Does it somehow suppress the exception that would otherwise be thrown by this illegal construction?
Ans: Construction not favored, but not illegal either. The Grouping Operator essentially is a device to make the function anonymous.
5: In 3, again, Grouping Operator seems to do nothing - this time, without any imaginable utility.
Ans: Passes in the
globalObject to the anonymous function - assumes that the globalObject would otherwise be inaccessible (...is that true?).
6: In 4, what does this construction do?
Ans: That construction is not actually executed.

[edited by: MarkFilipak at 7:19 pm (utc) on Mar. 20, 2008]

Achernar

5+ Year Member



 
Msg#: 3604898 posted 2:40 pm on Mar 22, 2008 (gmt 0)

Don't try to find a meaning to each part of the contruction.
You can't make it work without one of its components: the "grouping" (), the function(){}, and the final ().

Personally, I don't pass arguments to the anonymous function. Since it's only executed once, I already know what arguments it needs when I write the code.

MarkFilipak

5+ Year Member



 
Msg#: 3604898 posted 12:00 am on Mar 23, 2008 (gmt 0)

Achernar, I very much appreciate your comments!

> Don't try to find a meaning to each part of the contruction.
Why not?

> You can't make it work without one of its components...
> Personally, I don't pass arguments...
Oh sure. Now that I understand what it's doing, I will write this:
(function(){ self.myLib = {thingie : ..., ... }})();
or, if I'm not going to "pollute" global, this:
myLib = { thingie: ..., ... }

I didn't write the code. It is part of a library. I don't want to embarrass anyone so I'm not going to disclose from who's library it came, but I will say that you'd recognize it!

Thanks again for your insight. I'm in your debt.

PS: Regarding the use of the anonymous function, do you think my concern about a memory leak has any merit?

[edited by: MarkFilipak at 12:04 am (utc) on Mar. 23, 2008]

Achernar

5+ Year Member



 
Msg#: 3604898 posted 5:16 pm on Mar 24, 2008 (gmt 0)

>> Don't try to find a meaning to each part of the contruction.
> Why not?
It's a bit like arguing over why a word is spelled in a specific way.
You'll find as many reasons for "grouping ()" being logical, as reasons for it being wrong.

If you want a global variable, you don't declare it with "var y;". And if you need a local variable, just use "var z; z=document.getElement...()".

PS: Regarding the use of the anonymous function, do you think my concern about a memory leak has any merit?
I don't see why. There are several possibilities of memory leaks with other constructs or events, but not in this case.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved