2

I have an IIFE in my code, where there are few other IIFEs. All of them have names (so they aren't anonymous). I want to invoke some of IIFE later (i mean, yes they do their job at the beginning, but i want use them later), by other function. Like in example:

(function start()
{
  /* some code*/

  (function firstIIFE(param1, param2)
  {
    if (param1 && param2)
    {
       console.log('param1 ',param1, 'param2 ',param2);
       return;
    }
    /* some code done when IIFE originally was self-invoked */
  }(param1, param2));

  /* some code */
}());

function foo()
{
   start.firstIIFE(param1, param2);
}

Is it possible, to invoke (firstIIFE) IIFE later? Because i want this function to do some things with param1 and param2 (which i created after those IIFE was invoked)? Currently i got error like: Uncaught ReferenceError: param1 is not defined

ScriptyChris
  • 639
  • 4
  • 16
  • 48
  • 1
    `IIFE`=> __Immediately Invoked Function Expression__ Why do you want them to be executed later ? – Rayon Jan 10 '16 at 01:56
  • Because they do sort of things, which i want to be done with my new parameters (created after IIFE has done it's job). – ScriptyChris Jan 10 '16 at 01:57
  • 2
    You can have a variable which can hold a function expression and you can use that variable anywhere where you want that common manipulation to be done.. – Rayon Jan 10 '16 at 01:58
  • Invoking later, would mean just a regular function, it sorta defeats the entire purpose of using an IIFE. – adeneo Jan 10 '16 at 02:00
  • So - like in my example - i would do `var firstIIFE = (function(param1,param2){ /* code */}(param1,param2));` i could invoke it by `foo` function? – ScriptyChris Jan 10 '16 at 02:01
  • 3
    The answer is just so easy, stop using the immediately invoked function pattern, and use named functions, and you can call them whenever you want, and how ever many times you want. – adeneo Jan 10 '16 at 02:07
  • Ok, it worked with (named function). But what's the difference between `var foo = function(){};` and `function bar(){};` - when i want to invoke it later? Is it make a difference then? – ScriptyChris Jan 10 '16 at 02:09
  • 1
    Refer this for that: http://stackoverflow.com/questions/1013385/what-is-the-difference-between-a-function-expression-vs-declaration-in-javascrip – Rayon Jan 10 '16 at 02:10
  • What is your objective in using IIFEs? –  Jan 10 '16 at 06:01
  • I wanted to execute code of some function immediately - so IIFE does it. But later i have wanted to execute that IIFE again with some other parameters. – ScriptyChris Jan 10 '16 at 08:41

2 Answers2

3

The way your code is written, you won't be able to access firstIIFE() outside of start(), as it's an internal function. In order to access it later, you'll need to expose it some how, by either setting an external variable to that function, or moving it outside of start() and having start() just call the function, rather than defining it and then immediately executing it:

function firstIIFE(param1, param2) {
  if (param1 && param2) {
     console.log('param1 ',param1, 'param2 ',param2);
     return;
  }
  /* some code done when IIFE originally was self-invoked */
}

(function start() {
  /* some code*/

  firstIIFE(param1, param2);

  /* some code */
}());

function foo() {
   firstIIFE(param1, param2);
}

(At that point you probably don't need to call it firstIIFE(), since it doesn't follow the Immediately Invoked Function Expression pattern anymore, rather it's now just a normal function call).

rossipedia
  • 56,800
  • 10
  • 90
  • 93
1

The name of function expressions isn't accessible to the scope where they are created, and thus can't be invoked from that scope without storing a reference to the function in a variable.
But storing your functions in variables instead of declaring them has the side effect of not hoisting your function to the top of the current scope, which is something you rarely want.

You can do:

(foo = function myNameIsKnownOnlyToMyself() {
     ...
 })();

foo(); // again!

if you really love your IIFE pattern, but as others said, this is likely not the most elegant solution to your problem.

lleaff
  • 4,249
  • 17
  • 23
  • Why `foo` is global at this example? – ScriptyChris Jan 10 '16 at 02:22
  • @Chris92 Because in JavaScript when you use a variable name without having previously declared it in the current scope, JavaScript will look for it in the outer scopes until it ends up at the global scope, in which case it will check it as a property of said global object. As you can guess that behavior is error-prone, so current versions of JS allow you to deactivate it by using [Strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) in your functions or globally. – lleaff Jan 10 '16 at 02:24
  • Ok, right. But having `(var foo = function(){}());` is wrong IIFE? – ScriptyChris Jan 10 '16 at 02:28
  • 1
    Yes, you can't do that because JavaScript makes the [unfortunate](https://github.com/rust-lang/rust/issues/1698#issuecomment-3705066) distinction between a *statement* and an *expression*. Statements can only be "on their own line", while expressions can be used anywhere. Variable declarations can only be statements. – lleaff Jan 10 '16 at 02:30
  • And `var foo = (function(){}());` is also wrong IIFE? – ScriptyChris Jan 10 '16 at 02:32
  • 2
    That's valid (you can even leave out the outer parentheses), but `foo` will store whatever the function returns, not the function itself, unless you make it return itself by naming it: `var foo = function imFoo() { return imFoo; }();` – lleaff Jan 10 '16 at 02:35