7
\$\begingroup\$

I am wondering if the self invoking function as displayed below, mainly the part of using the same function twice ('foo')('bar'), would ever be seen as a good practice?

And more important, is there a good reason to use this? Personally in this particular example I would rather go for multiple attributes and loop those.

The HTML is just filler.

<!DOCTYPE html>
<meta charset='utf-8'>
<title>Foo Bar Foobar</title>
<p id='foo'>Foo</p>
<p id='bar'>Bar</p>
<p>Foobar</p>
<script>
(function foobar(id) {
    var element = document.getElementById(id);
    element.style.color = 'red';
    element.style.textIndent = '10px';

    // Return self
    return foobar;
})('foo')('bar');
</script>
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note that in IE (up to and including version 8 I think) named function expresssions became global variables regardless of the scope in which they were created. \$\endgroup\$
    – RobG
    Oct 4, 2012 at 0:24
  • \$\begingroup\$ Confirmed that foobar in my code is global in IE8. But scope does seem to matter. Writing another function inside foobar will in no way of programming it become global. (tested with IE8 mode in IE9) \$\endgroup\$
    – René
    Oct 4, 2012 at 12:36

1 Answer 1

5
\$\begingroup\$

Wow. Basically you wrote Code A but in a cool functional programming style.

Code A:

(function(){
    function foobar(id) {
        var element = document.getElementById(id);
        element.style.color = 'red';
        element.style.textIndent = '10px';
    }
    for(var i = 0, len = arguments.length; i < len; i++){
        foobar(arguments[i]);
    }
}('foo', 'bar'));

Self invoking functions are good for three situations.

  1. To perform some startup functions onload. (Most likely your case)
  2. To save results from a expensive operation into a loop up table.

Example:

var primeTable = (function(){
    var primeObject = {}
    // calculates and stores primes from 100 to 1000 in primeObject
    return primeObject;
})();   

3. To create private variables, which is normally called a Module Design Pattern.

Example:

var box = (function () {
    var key = Math.floor(Math.random() * 1e5).toString(16);
    return {
        open : function(val){
            return (val === key) ? "Box has opened." : "Wrong Key";
        },
        setKey : function (oldKey, newKey) {
            if (oldKey === key) {
                key = newKey;
            }
        }
    }
})();

Overall, if you want to follow KISS philosophy then I think you should wrap everything in a closure and call the function traditionally.

(function(){
    function foobar(id) {
        var element = document.getElementById(id);
        element.style.color = 'red';
        element.style.textIndent = '10px';
    }
    foobar('foo');  
    foobar('bar');  
})();
\$\endgroup\$
2
  • \$\begingroup\$ Thank you for this very extensive explanation. Seems like we both think this is just another way of writing the same, but worse practice than some of the best practice alternatives. Nice to see how versatile programming languages can be. \$\endgroup\$
    – René
    Oct 2, 2012 at 6:33
  • \$\begingroup\$ +1 Good answer. I think the last example is best as it's very clear what the code is doing, so good for maintenance and easy for compilers to optimise if they can. \$\endgroup\$
    – RobG
    Oct 4, 2012 at 0:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.