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\$

closed as off-topic by Jamal Nov 8 '16 at 22:04

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

  • 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 '12 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 '12 at 12:36
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\$
  • \$\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 '12 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 '12 at 0:26

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