Immediately Invoked Function Expressions

(También llamadas Self-Invoking Anonymous Functions)

Ya sea que necesites definir una función como
function foo() {}
o como
var foo = function() {}
terminas con un identificador para una función, la cual puedes invocar utilizando paréntesis
foo();
No tiene sentido que la función pueda ser invocada simplemente usando () después de su declaración?
function(){ /*código */ }(); // SyntaxError: Unexpected token ( 
Cuando el parser encuentra la palabra function, ya sea en el scope global o dentro de una función, la trata como si fuera una function declaration, y no como una function expression, por lo que piensa que es una function declaration sin nombre y arroja un error de sintáxis porque las function declarations requiren un nombre.

Y si le asignamos un nombre a la función?

Si le asignamos un nombre a la función y usamos paréntesis inmediatamente después, el parser también arroja un error de sintáxis, aunque por una razón distinta. Cuando usas paréntesis después de una declaración (statement) los paréntesis son tratados como operador agrupador (como para controlar el orden de una evaluación).
function foo() { /* código */ }(); //SyntaxError: unexpected token )

function foo() { /* código */}(1); //No hay excepción, pero no hace nada porque equivale a:

function foo(){ /* código */}
(1);
		
Afortunadamente, es fácil solucionar el error de sintáxis. Hay muchas maneras de lograr esto, pero la más usada es utilizando paréntesis para envolver la expresión de la función. Ya que en JavaScript, los paréntesis no pueden contener statements, cuando el parser encuentra la palabra function, lo tratará como un function expression y no un function declaration.

Muy buen árticulo sobre el tema
Código