views:

38

answers:

4

Hi. I'm new to javascript and I am looking through some Raphael demo code. I'm confused by how this is working...

if (R) {
    (function (dx, dy, R, value) {
        var color = "hsb(" + [(1 - R / max) * .5, 1, .75] + ")";
...

From what I can see this is declaring an anonymous function which takes 4 arguments. How is this function invoked when this function doesn't have a name??

Demo page.. http://raphaeljs.com/github/dots.html

JS file.. http://raphaeljs.com/github/dots.js

+1  A: 

you didn't include enough of the code to tell. looking at the source, this method is executed immediately. ignoring the contents of the function, it looks like this

(function (dx, dy, R, value) {

// ... stuff

dot[0].onmouseover = function () {
    if (bg) {
        bg.show();
    } else {
        var clr = Raphael.rgb2hsb(color);
        clr.b = .5;
        dt.attr("fill", Raphael.hsb2rgb(clr).hex);
    }
    lbl.show();
};

// more stuff

})(leftgutter + X * (j + .5) - 60 - R, Y * (i + .5) - 10, R, data[o]);

this all happens within a loop, and the variables are referenced in an event handler method. the anonymous method creates a new scope so the values at the time the loop runs are preserved, rather than having every event handler point to the very last value the variable holds.

lincolnk
+1  A: 

It’s called 28 lines later:

...
    })(leftgutter + X * (j + .5) - 60 - R, Y * (i + .5) - 10, R, data[o]);

so those are the four arguments.

If you don’t give a function a name, the only thing you can do with it is call it right there or pass it to someone else. This is pretty standard if you’re familiar with event listeners:

window.addEventListener("load", function(event) {
    document.body.innerHTML = "hello";
}, false);

In this case, it’s used to control the scope of variables, to guarantee that their values are not reused after an iteration of the loop completes. Many libraries wrap the entire script in a function block, solely to create a new scope. (Unlike in other curly brace languages, a { } block alone does not create a new scope.)

(function() {
    var foo; // guaranteed to not leak or interfere with someone else's foo
    // 6000 lines ...
})();

Read about JavaScript Scope and Closures.

jleedev
Thanks, I'll read up on event listeners.
El Ronnoco
+2  A: 

To briefly answer your question it is invoked immediately upon decleration.

You left out an important part, the end of the function definition:

})(leftgutter + X * (j + .5) - 60 - R, Y * (i + .5) - 10, R, data[o]);

What this says is }, which ends the function, then ), which ends the parenthesis that opened with (function. If what remains looks like an argument list, that's because it is.

An illustrative example:

(function(arg){ alert(arg); })("Hi!");
Sorpigal
+1  A: 

An anonymous function is created and called on the fly. A simplified version would be

function(a){<some method code>}(x);

In this the value x is passed as a in the function. In your example the function is later being invoked:

(function (dx, dy, R, value) {
    var color = "hsb(" + [(1 - R / max) * .5, 1, .75] + ")";
    ...
})(leftgutter + X * (j + .5) - 60 - R, Y * (i + .5) - 10, R, data[o]);
Ara