25

I'm trying to immediately invoke a function without using IIFE pattern (enclosing a function definition inside parentheses). Here I see two scenarios:

  1. When a function declaration is invoked immediately: gives SyntaxError.

  2. When a function expression is invoked immediately: executes successfully.

Example 1: gives SyntaxError

//gives `SyntaxError`
function() {
    console.log('Inside the function');
}();

Example 2: Executes without any error

// Executes without any error
var x = function() {console.log('Inside the function')}(); // Inside the function

So, I have these doubts:

  • With this approach, why does it give an error for function declaration but not for function expression?
  • Is there a way we can immediately invoke a function declaration without using IIFE pattern?
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
Aaditya Sharma
  • 2,125
  • 1
  • 19
  • 34
  • 3
    Quick question. IIFE invokes code immediately and creates a scope. So what do you expect with *immediately invoke a function declaration without using IIFE pattern* – Rajesh May 13 '19 at 08:38
  • The main question here is, does JavaScript provides any ways for us to immediately invoke a function declaration without wrapping them inside parentheses? – Aaditya Sharma May 13 '19 at 08:45
  • No you cannot. Anything which is written inside parentheses will be evaluated in javascript. So if you write function inside parens, then it will evaluate aka invoke the function. You can just write `(4)` on javascript console and it will give you 4 as output. By writing 4 in parens you are just evaluating a literal and hence it gives 4 back. – Navjot Singh May 13 '19 at 08:46
  • I see people here are calling the 2nd example as `IIFE`. So, do we really call it an `IIFE`, if it doesn't use the **IIFE Pattern**? – Aaditya Sharma May 13 '19 at 08:50
  • 1
    `+function(){console.log('done')}()` and `new function(){console.log('done')}()` seem to work. I wonder, what's going under the hood here. – Aaditya Sharma May 13 '19 at 08:59
  • 5
    "does JavaScript provides any ways for us to immediately invoke a function declaration without wrapping them inside parentheses?" - Yes - it only needs to disambiguate that it is function expression and not a function declaration, which can be done by e.g. prefixing with any operators (e.g. `!function() { .... }`). "why does it give an error for function declaration but not for function expression?" Have you noticed what IIFE _means_? "Immediately invoked **function expression**." It is not IIFD/E. Function invocation is an expression - and you cannot use a statement inside an expression. – Amadan May 13 '19 at 09:07
  • 3
    @AadityaSharma what is an "IIFE pattern"? IIFE means an immediately invoked function expression. If you have a function expression and invoke it immediately, that's an IIFE. Your second example is exactly that - a function expression which you invoke. Same with `+function(){}` although it's more hacky - it merely forces this to be evaluates as an expression instead of declaration. – VLAZ May 13 '19 at 09:56
  • @all-the-downvoters - It'd be helpful if you can explain the reason(s), for the benefit of others. – Aaditya Sharma May 13 '19 at 13:19
  • 1
    see: https://developer.mozilla.org/en-US/docs/Glossary/IIFE – Matt May 13 '19 at 14:01
  • See [plus sign in front of function name](https://stackoverflow.com/q/13341698/1048572) or [What does the exclamation mark do before the function?](http://stackoverflow.com/q/3755606/1048572) – Bergi May 13 '19 at 20:49
  • I see @Bergi has updated the title. Doesn't the new title alter the meaning of the original question being asked? Earlier it was **Immediately invoke a function declaration without using IIFE pattern**. As per MDN, IIFE is a design pattern. See - https://developer.mozilla.org/en-US/docs/Glossary/IIFE – Aaditya Sharma May 13 '19 at 21:01
  • 1
    @AadityaSharma The original title didn't make sense. It's impossible to immediately invoke function *declaration*s, and its impossible to immediately invoke a function expression without it being an IIFE. The body of the question is more clear, and the answers are fine. So adjusting the title was the best I could do without voting to close (as either unclear, or duplicate on [function declaration vs expression](https://stackoverflow.com/q/336859/1048572)). – Bergi May 13 '19 at 21:29

6 Answers6

16

In your code you don't have name for the function that's the reason for syntax error. Even if you would had name it would have thrown error.

function func(){
  console.log('x')
}();

The reason is the function declaration doesn't return the values of the function however when you wrap function declaration inside () it forces it be a function expression which returns a value.

In the second example the function() {console.log('Inside the function')} is considered expression because it's on RightHandSide. So it executes without an error.

Is there a way we can immediately invoke a function declaration without using IIFE pattern

You can use + which will make function declaration an expression.

+function(){
  console.log('done')
}()

If you don't want to use + and () you can use new keyword

new function(){
  console.log('done')
}

Extra

A very interesting question is asked by @cat in the comments. I try to answer it.There are three cases

+function(){} //returns NaN
(+function(){return 5})() //VM140:1 Uncaught TypeError: (+(intermediate value)) is not a function
+function(){return 5}() //5

+function(){} returns NaN

+ acts as Unary Plus here which parses the value next to it to number. As Number(function(){}) returns NaN so it also returns NaN

(+function(){return 5;})() returns Error

Usually IIFE are created using (). () are used to make a function declaration an expression + is short way for that. Now +function(){} is already an expression which returns NaN. So calling NaN will return error. The code is same as

Number(function(){})()

+function(){return 5;}() returns 5

In the above line + is used to make a statement an expression. In the above example first function is called then + is used on it to convert it to number. So the above line is same as

Number(function(){return 5}())

In the proof of statement "+ runs on after the function is called" Consider the below snippet

console.log(typeof +function(){return '5'}());

So in the above snippet you can see the returned value is string '5' but is converted to number because of +

Maheer Ali
  • 32,967
  • 5
  • 31
  • 51
  • 2
    ...but note that using `new` like that will have the side effect of constructing an object using the provided function as its constructor (and then immediately garbage collecting it, since you don't save the returned value). Try e.g. `let foo = new function() { console.log("in function") }; console.log(foo); console.log(foo.constructor);` to see what I mean. – Ilmari Karonen May 13 '19 at 09:46
  • 2
    Can you say why or how `+function(){}` is (correctly) `NaN`, and `(+function(){ return 5 })()` is `(+ (intermediate value)) is not a function`, yet `+function(){ return 5 }()` is `5`? – cat May 13 '19 at 14:14
  • 2
    @cat Your question worth to be answered in original answers rather than comments. I have added a detailed answer. Check it out. If any confusion ask me – Maheer Ali May 13 '19 at 14:44
  • @MaheerAli this was helpful - In the second example the `function() {console.log('Inside the function')}` is considered expression because it's on RightHandSide. – Aaditya Sharma May 13 '19 at 18:01
  • @AadityaSharma Yes absolutely. – Maheer Ali May 13 '19 at 18:53
14

A function declaration, like

function foo() {
}

defines (and hoists) the variable name foo as a function in the current scope. A function declaration doesn't evaluate to a value; it just does something, a bit like an if does something (rather than evaluate to a value).

You can only invoke values which are functions, eg

<somevalue>()

where somevalue is a variable name that refers to a function.

Note that function declarations require function names, because otherwise there's no variable name to assign the function to - your original

//gives `SyntaxError`
function() {
    console.log('Inside the function');
}();

throws not because of the () at the end, but because of the lack of a name.

You can put parentheses at the end of a function declaration, as long as there's something inside the parentheses - but these parentheses do not call the function, they evaluate to a value:

function x() {
    console.log('Inside the function');
}(console.log('some expression inside parentheses'));

The interpreter sees these as two separate statements, like

function x() {
    console.log('Inside the function');
}
// completely separate:
(console.log('some expression inside parentheses'));

The inside of the parentheses gets evaluated and then discarded, since it doesn't get assigned to anything.

(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)

CertainPerformance
  • 260,466
  • 31
  • 181
  • 209
  • Might help to have the last example without `()` to show it throws. – Kaiido May 13 '19 at 08:35
  • It gives an error with a named function too `function kaka() {console.log('Inside the function');}();` – Aaditya Sharma May 13 '19 at 08:36
  • @CertainPerformance - This example just executed whats there inside the last set of paratheses, ignoring the function declaration. `(console.log('some expression inside parentheses'));` – Aaditya Sharma May 13 '19 at 08:38
  • 1
    Your answer lacks ,any alternative to invoke function immediately except iife. – Shubh May 13 '19 at 08:39
  • @AadityaSharma The function declaration is not ignored - the variable name `x` gets assigned (and hoisted) to that function in the current scope. But `x` is never called, so you don't see `Inside the function`. – CertainPerformance May 13 '19 at 08:39
  • @Shubh Yes, that's because function declarations cannot be immediately invoked - they *do something*, rather than evaluate to a value. They're not expressions. You'd have to use a function expression instead, to call it immediately. – CertainPerformance May 13 '19 at 08:41
  • @CertainPerformance - but exactly I'm looking for is: `x` to get called without enclosing it inside parentheses. – Aaditya Sharma May 13 '19 at 08:42
  • If `x` is a function declaration, you can't call it immediately, see above comment and first part of answer - either make it a function expression instead, or write `x()` – CertainPerformance May 13 '19 at 08:43
  • @CertainPerformance This statement doesn't really seem to be right **throws error not because of the `()` at the end, but because of the lack of a name.** It **gives an error** with a named function too `function kaka() {console.log('Inside the function');}();` – Aaditya Sharma May 13 '19 at 08:54
  • @AadityaSharma Yes, **once** you give it a name, it throws on the `()` at the end - as the last part of the answer describes, `(Empty parentheses are forbidden because they can't be evaluated to a value, similar to how const foo = () is forbidden)`. Before you give it a name, it doesn't throw at the `()`, because the parser threw *before*, when the nameless function declaration was encountered – CertainPerformance May 13 '19 at 08:56
2

The E in IIFE stands for expression, and without the wrapping parenthesis your function is not evaluated as an expression thus the syntax error.

creating an expression is a way of tricking the interpreter and be able to invoke the function immediatly

(function() {
    console.log('Inside the function');
})();

In your example you have a function statement followed by the grouping operator, but it's syntactically incorrect for two reasons, first it doesn't have a name, and second because the grouping operator must have an expression inside it, infact if you add a valid one the error will disappear, still you won't obtain your desired result.

function foo() {
    console.log('Inside the function');
}();

function foo() {
    console.log('Inside the function');
}(1+2);
Karim
  • 7,479
  • 1
  • 18
  • 31
1

In order to invoke something, it has to be a function value, a declaration just declares a name, and does not evaluate to the function value itself, hence you cannot invoke it.

A declaration cannot be invoked for the above reason. You have to end up with an expression somehow, either through assignment or grouping (IIFE). So that is a no.

If you give us more context on why you would want to do that, maybe we can help with suggestions.

Slawomir Chodnicki
  • 1,447
  • 9
  • 15
1

Not sure why you would want to do it, but:

Is there a way we can immediately invoke a function declaration without using IIFE pattern?

Well, if for function declaration you mean using the keyword function as in:

function name() { return this.name; }

As far as I know, no. You need the extra parentheses to tell the runtime not to assign the function to a name variable, if I understand this stuff right.

Now, what you actually can do is to use Function as in:

new Function('console.log("ey there")')();

Which will execute the console.log code. No need for IIFE here. But I don't see how this could be better than an IIFE.

Sergeon
  • 5,628
  • 17
  • 37
1

you can call in either below ways -

~function(){console.log("hi")}()
!function(){console.log("hi")}()
+function(){console.log("hi")}()
-function(){console.log("hi")}()
(function(){console.log("hi")}());
var i = function(){console.log("hi")}();
true && function(){ console.log("hi") }();
0, function(){ console.log("hi") }();
new function(){ console.log("hi") }
new function(){ console.log("hi") }()
Samyak Jain
  • 696
  • 1
  • 7
  • 12