Welcome to WebmasterWorld Guest from 54.167.0.111

Forum Moderators: open

Message Too Old, No Replies

Anonymous library loader?

Mysterious code found in the wild.

     

MarkFilipak

5:04 am on Mar 19, 2008 (gmt 0)

5+ Year Member



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

6:43 pm on Mar 19, 2008 (gmt 0)

5+ Year Member



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

12:50 am on Mar 20, 2008 (gmt 0)

5+ Year Member



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

11:43 am on Mar 20, 2008 (gmt 0)

5+ Year Member



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

7:00 pm on Mar 20, 2008 (gmt 0)

5+ Year Member



> 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

2:40 pm on Mar 22, 2008 (gmt 0)

5+ Year Member



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

12:00 am on Mar 23, 2008 (gmt 0)

5+ Year Member



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:16 pm on Mar 24, 2008 (gmt 0)

5+ Year Member



>> 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.
 

Featured Threads

Hot Threads This Week

Hot Threads This Month