What is this line at the top of some Greasemonkey scripts?
Asked Answered
D

3

9

Background: I have a self-taught hobbyist level of understanding of C++, which has translated into a similar understanding of javascript. As an attempt to understand javascript better, I decided to write a Greasemonkey script that would solve a problem with how Google handles multiple results from the same domain.

I wrote my script, and it was surprisingly easy. Now I feel like this script could be useful to others, so I'd like to release it. Before I do that though, I'd like to be certain I'm not releasing irresponsible code.

I know poor garbage collection is often cited as a problem with extensions, and did some research about what I would need to do in javascript to prevent that. It seems like the answer is any memory that is wrapped in a function will be reclaimed when that function exits. This seems to explain why a few popular scripts I looked at were wrapped in an otherwise useless function.

This leads me to these questions:

  1. What should I do with my basic javascript function to ensure that it doesn't leak memory?
  2. Is this, which I've seen in many scripts, an answer:

    (function(){  
        //code goes here    
    })();
    
  3. In the above code, what is the purpose of the first parentheses? It seems redundant to me.

  4. While I was attempting to understand that line, I rewrote it as:

    (function main(){  
        //code goes here  
    })   
    main();  
    

The idea being that this was just calling the the previously unnamed function. This didn't work though, why?

I'm more interested in general answers, but in case it's needed here is my current code: http://pastebin.com/qQWKfnJT

Displant answered 17/8, 2012 at 1:15 Comment(2)
This has nothing to do with Greasemonkey, and such wrapping is almost never needed there. Additionally, both Firefox and Chrome wrap scripts in anonymous functions by default.Archle
possible duplicate of What is this construct in javascript?Archle
T
9

This pattern (wrapping a function in a pair of parenthesis and then placing another pair after the first pair) is called the " I mmediately I nvoked F unction E xpression" pattern (IIFE for short). What it does is define an anonymous function and then execute it immediately. The first set of parentheses mark the function as being an expression, rather than a statement. The second set execute the function returned from the first expression:

// This:
(function(){
    // Todo: Add code
})();

// Translates *approximately* to this:
var _anonymous_function_2723113 = function() {
    // Todo: Add code
};
_anonymous_function_2723113();
delete _anonymous_function_2723113;

As for why the function does not work when you give it a name, I would recommend reading up on kangaxx's article on the subject, especially where he touches on Named Function Expressions. The short of it is that when you have a named function expression (rather than a statement), the name is supposed to only be available to the function's scope.

So much for three and four - as for avoiding memory leaks, the IIFE is not a way to avoid memory leaks (as @elclanrs has pointed out, it merely helps you avoid polluting the global scope). To avoid memory leaks avoid circular references (and remember, closures can be a source of circular references).

Good luck, and enjoy yourself!

Tonisha answered 17/8, 2012 at 1:30 Comment(3)
Isn't "Immediately Invoked Function Expression" (IIFE) the more common term?Archle
@BrockAdams - yes it is - I've fixed that now. Thanks!Tonisha
kangaxx's article is no longer on Github but you can find it on the Wayback Machine at web.archive.org/web/20130202165232/http://kangax.github.com:80/…Printable
A
0

Here is an example, where anonymous functions can be used: Lets have 4 elements with ids: id_1, id_2, id_3... We want too loop over each of them and assign onclick event.

for (var i=0; i<5; i++) {
    document.getElementById("id_"+i).onclick = function()  {alert(i)}
}

When you click elements however each of them will alert the same - 4. The reason is that in the JavaScript closure only the last value is stored for local variables. What you can do:

for (var i=0; i<5; i++) {
(function(n){
    document.getElementById("id_"+n).onclick = function() {alert(n)};
})(i);

}

Astonishment answered 17/8, 2012 at 1:50 Comment(0)
J
-1

There are so many answers to this question in SO already... It's a self executing function. It's used in many cases to protect your code from the global scope. It's written in other ways too:

function(){}()
(function(){})()
(function(){}())
!function(){}()
(function(){}).call(this)
Jeweljeweler answered 17/8, 2012 at 1:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.