8

The common practise for creating modules is to wrap them in parens so you won't leak any variables outside of the module (when concatenating etc).

There is also void operator, which evaluates a given expression and returns undefined. (See on MDN)

I wonder what is the reason behind preferring wrapping functions in parens instead of using void. Is it historical, is it something related to concatenation, else?

I know that you can have problems with concatenation when one of the files has a missing a semicolon, leading to nasty problems till you notice it.

Examples

Say, module1.js (notice the missing comma):

(function () {
    return function () {
        console.log('module1. I should not be called');
    };
})()

and, module2.js:

(function () {
    return function () {
        console.log('module2. I should not be called either');
    };
})();

If you concat these scripts into a bundle, it will produce this:

(function () {
    return function () {
        console.log('module1. I should not be called');
    };
})()(function () {
    return function () {
        console.log('module2. I should not be called either');
    };
})();

Since both modules(files) return a function, the second supposedly IIFE becomes an invocation of the return value of the first module, effectively calling console.log. The common workaround for this is to declare your module with !(function (){})(); which forces the returned value to be a boolean.

If however, you were to use void, like:

void function () {
    return function () {
        console.log('module1. I should not be called');
    };
}()

The concatenated file will still be wrong, but you will notice the error on the first run, therefore more easily noticed. See below.

void function () {
    return function () {
        console.log('module1. I should not be called');
    };
}()void function () {
    return function () {
        console.log('module2. I should not be called either');
    };
});

This throws Unexpected token void. As fas as the modules are concerned, I believe !(function(){}() and void function(){}() achieve the same effect. But I feel like void looks more clean (subjective) than wrapping a function with params and prepending ! to it.

I am missing something? Wouldn't it be better if we used void?

Umur Kontacı
  • 35,099
  • 7
  • 69
  • 94
  • 3
    The proper solution to your problem is to put the semicolon where it belongs, not to choose a different module header. – Bergi May 19 '15 at 02:49
  • 1
    @Bergi You're missing the entire point of the OP! He is specifically *trying* to make code more robust to potential human errors, and your solution is, "well, just don't make any errors"?! The only way to guarantee no errors is to do nothing. We *all* make errors, and need to find ways to design safety into the process. – Mike Williamson Jun 10 '16 at 18:11
  • @MikeWilliamson: I linter/stylechecker/etc could find such mistakes as well and guarantee (as a part of your build process) that they don't happen. Or we could blame the "bundle" concatenation script whose responsibility it actually is to take care of these things. I believe that such setting things up properly is better style than to take mostly unnecessary precautions in each and every file - and that's probably also the reason why these things (`void …`, [`;(…)`](http://stackoverflow.com/q/1873983/1048572), [`!…`](http://stackoverflow.com/q/5827290/1048572)) never took off. – Bergi Jun 10 '16 at 21:35
  • @MikeWilliamson: See also [here](http://stackoverflow.com/q/24067605/1048572). So "*Wouldn't it be better if we used `void`?*" could also be answered with "there are simpler ways to reach the same goal". – Bergi Jun 10 '16 at 21:47

1 Answers1

5

Well, many JavaScript programmers think void is confusing and redundant, especially Douglas Crockford who calls it one of the "Bad Parts" of JavaScript.

Preceding a function definition with void can be especially confusing. In languages like C++, it means "This is a type of function that doesn't return a value." In JavaScript, void doesn't define anything; instead it evaluates the function (or other expression) and returns the value undefined. So you don't see it much in JavaScript code.

For more info on using ! to precede modules, check out this StackOverflow answer.

Also make sure to read Ben Allman's original blog post on IIFE's.

Community
  • 1
  • 1
jkdev
  • 9,037
  • 14
  • 52
  • 75
  • 1
    As you said, it is *typically* better not to use `void`. But I feel as if this is the exception that proves the rule: here, `void` will *in effect* not return a value, since the value `undefined` is immediately discarded. So, in this case, wouldn't it be *better* to use `void`? It seems to me that this case even follows the logic intrinsic behind Crockford's original issue with it. Unless I am missing something... and there's **lots** to miss, when it comes to odd Javascript behaviors. – Mike Williamson Jun 10 '16 at 18:14
  • 1
    Usually an IIFE doesn't return a value anyway. No need to void it. But if you *want* it to return a value, then do this: `var valueFromIIFE = (function() { return "This value"; })();` In other words, you'd need to include a return statement *and* assign the returned value to a variable. And if that's the case, then you *don't* want to turn your nice shiny new returned value into undefined. – jkdev Jun 10 '16 at 19:27