0

Here are two ways of writing a function that includes an IIFE:

    function f() {
        let count=0;
        return function() {
            return ++count;
        }
    }

    const g = (function() {
        let count=0;
        return function() {
            return ++count;
        }
    })();

f() returns function () { return ++count; }

When g() is run several times, it returns 1, 2, 3... which is the intention.

Now another example:

    function f() {
        return "This is f()";
    }

    const g = (function() {
        return "This is g()";
    })();

In this case f() returns "This is f()" and g() is a script error.

I've done a lot of coding in C-ish languages, but am new to JavaScript. What am I missing?

In response to the first answer, here is an executable code snippet. If function f(){...} were the same as const f = (function () {...})() I would expect both to run. They do not.

function f() {
    return "This is f()!";
}

console.log(f());

const h = f;

console.log(h());

const g = (function() {
  return "This is g()";
})();

console.log(g());
  • 1
    `g()` is an IIFE. See https://stackoverflow.com/questions/8228281/what-is-the-function-construct-in-javascript. It calls the inner function immediately. – Barmar May 27 '22 at 19:26

2 Answers2

0

Functions in JavaScript are first class objects, meaning you can treat them as any other object in JavaScript.

function f (){} is regular function definition, which you can also write as

let f = function(){}

(function{})() is basically the same as

let f = function () {}
f = f() // You reassign f to be the return value from the function that f was assigned to

You bottom case const g = (function() {return "This is g()";})(); can be written as:

let g = function() {
    return "This is g()"
}
g = g() // You are reassigning g to be "This is g()"

// Trying to call g again is like calling a string
// and it should return an error saying that g is not a function
g()

Update

There difference in your extended example is that f is a function that returns a function (always), while g immediately gets assigned to the inner "regular function", and return numbers.

function f() {
    let count = 0;
    // --- Will always return this, a function ----
    return function () {
        return ++count;
    }
    // --------------------------------------------
}

const g = (function () {
    let count = 0;
    return function () {
        return ++count;
    }
})() // <--- Here you call the (function () {}) immediately, thus you assign g to the inner returned function

console.log(f);
console.log(f()); // returns a function
console.log(g); 
console.log(g()); // returns a number
console.log(g());
console.log(g());
console.log(g());

To make f equivalent to g you have to do this:

function f() {
    let count = 0;
    return function () {
        return ++count;
    }
}
f = f() // Here
Naphat Amundsen
  • 1,519
  • 1
  • 6
  • 17
  • I know `function f(){}` and let `f = (function{})()` should be the same. But in the example above, `function f(){...}` works. `const g = (function(){...})();` fails. Look at the final code snippet added to the question above. – Jeff Hester May 27 '22 at 19:37
  • @JeffHester It is as I said really, you are assigning `g` to a string, and you are attempting to call it: `g()`, if you change `console.log(g())` to `console.log(g)` you will see that are attempting to call the string `"This is ig()"` – Naphat Amundsen May 27 '22 at 19:40
  • OK... The simple example was poorly stated. My bad. But now take a look at the example below. I understand that I am doubtless being an idiot, but why does `function f() {...iife...}` followed by `f();` fail, while `constant g = (function)() {...exactly the same code...})(); g();` succeed? – Jeff Hester May 27 '22 at 20:03
  • Hmmm... In both cases `const myVar = (function(){...})();` is assigning myVar the value returned when the function executes. Check. In the first case f() just returns `function(){return ++count;}` when it is called. In the second case `(function(){...})` executes immediately, returning the function `function() {return ++count;}`. – Jeff Hester May 27 '22 at 20:17
0

The behavior of the following snipped clarifies my question...

And I think I see the answer. In the first case, f() doesn't do anything until it is called. And when it is called it returns the string.

In the second case, (function(){})() executes immediately, and returns the function itself.

Like the name says, Immediate execution. Thanks for helping me ask the right question.

function f() {
        let count=0;
        return function() {
            return ++count;
        }
    }

const g = (function() {
        let count=0;
        return function() {
            return ++count;
        }
    })();
    
 console.log(f);
 console.log(f());
 console.log(g);
 console.log(g());
 console.log(g());
 console.log(g());
 console.log(g());
  • Hi, I added an update to my answer. I also suggest that you put this snippet in the original question rather than submitting it as an answer, as it technincally isn't an answer – Naphat Amundsen May 27 '22 at 20:20
  • I tried to do that in the first place, but it wouldn't let me. I got an error something like "beyond the suggested number of edits". – Jeff Hester May 27 '22 at 20:26
  • Oh ok, that's unfortunate – Naphat Amundsen May 27 '22 at 20:27
  • Indeed. And again, thanks. I recognized the problem with the immediate response (which is why they are called "Immediately Invoked Function Expressions" -- duh), then saw your modified answer. I was missing the obvious thing. I should probably put "JavaScript is interpreted, not compiled" on my white board in big letters. – Jeff Hester May 27 '22 at 20:32
  • No worries! And take it easy on yourself! Even the best experience moments like this from time to time. I am glad I could help. – Naphat Amundsen May 27 '22 at 20:39
  • And I'm far from the best. ;-) – Jeff Hester May 27 '22 at 20:43
  • With apologies to whatever ad agency promotes a certain Nevada city... "What happens in an IFFE stays in the IFFE. But you can take your winnings home." – Jeff Hester May 27 '22 at 23:22