Calling function inside IIFE - javascript

I have the following code:
function doStuff() {
var increaseNumber = 0;
function doSomeStuff() {
console.log(++increaseNumber);
}
return doSomeStuff();
};
doStuff();
When function “doStuff” is executed, function “doSomeStuff”, which is inside function “doStuff”, gets triggered via “return doSomeStuff()” and increments variable “increaseNumber” by 1 each time it is called. If I change “return doSomeStuff();” to “return doSomeStuff;”, calling “doStuff” via “doStuff()” doesn’t work, as I’d assume.
Furthermore, I have the following code which yields the same result as the previous code:
var doStuff = (function () {
var increaseNumber = 0;
function doSomeStuff() {
console.log(++increaseNumber);
}
return doSomeStuff;
})();
doStuff();
In this code, an IIFE is stored inside variable “doStuff”. Inside the IIFE, function “doSomeStuff” is stored and apparently gets triggered via “return doSomeStuff” and increments variable “increaseNumber” by 1 each time it is called via “doStuff()”. When I change “return doSomeStuff;” to “return doSomeStuff();”, the code doesn’t work as laid out anymore.
When:
return doSomeStuff();
})();
//doStuff();
the IIFE and “doSomeStuff” are executed once and increaseNumber is = 1. Calling the IIFE further times via “doStuff()” doesn’t work, because of error: “JavaScript error: doStuff is not a function”.
There are mostly two things that I don’t understand here:
Why does the code work when “return doSomeStuff;”. I don’t see how this triggers function “doSomeStuff”, as the () is missing. When I call a function, I make sure to add (). That’s how I learned it.
ABOVE EVERYTHING: Why can I not call “doStuff” as a function when I change “return doSomeStuff;” to “return doSomeStuff();”?
You will notice that I’m still a Javascript novice rather. I hope I’m not repeating a question here (I honestly couldn’t find anything via search or on Google which would answer my query).
Thanks a million for any hints.

In this code, an IIFE is stored inside variable “doStuff”
No, the IIFE is run immediately, and its return value is stored in doStuff. So if you want doStuff to be a function that you can call multiple times, you need to return a function.
Why does the code work when “return doSomeStuff;”. I don’t see how this triggers function “doSomeStuff”, as the () is missing.
It's not going to trigger doSomeStuff, not on its own. The code inside the IIFE is just trying to create the function, not actually run it. The spot where you call the function is the () at the end of doStuff().
Why can I not call “doStuff” as a function when I change “return doSomeStuff;” to “return doSomeStuff();”?
Because in that case, your IIFE is returning a number, and then that number gets assigned to doStuff.

In Javascript functions are just like any other objects, we can return a function from another function, they can be passed as arguments to other functions etc.
When you return doSomeStuff; you are returning the function.
When you return doSomeStuff(); you are returning the value returned by invoking doSomeStuff function. It is same as
var result = doSomeStuff();
return result;
Now to answer the questions.
1. Why does the code work when “return doSomeStuff;”. I don’t see how this triggers function “doSomeStuff”, as the () is missing. When I call a function, I make sure to add (). That’s how I learned it.
As mentioned above you are returning the function here, Which gets stored to var doStuff. And it gets executed when you do doStuff()
2. ABOVE EVERYTHING: Why can I not call “doStuff” as a function when I change “return doSomeStuff;” to “return doSomeStuff();”?
If you change to return doSomeStuff(); you are not returning function anymore, instead you are returning the value returned by doSomeStuff function and gets stored to var doStuff. You can do () only on functions, since doStuff is not function you cant do doStuff()

In JavaScript return func(); returns the value which is returned by func(). On the other hand return func; returns a function, that itself returns the value returned by the function func. Both are two different things.
return func returns a function object. In javascript functions are treated as objects. return func will return the callable function object. Returning func() returns the value returned by the callable function.

Here is how it works.
Q1 (rephrased): "Why does this work?"
var doStuff = (function () {
var increaseNumber = 0;
function doSomeStuff() {
console.log(++increaseNumber);
}
return doSomeStuff;
})();
doStuff();
A1: Let's break it down to simple steps.
The variable doStuff is declared.
The IIFE runs, returning the function declaration doSomeStuff, which gets assigned to the variable doStuff.
Since the variable doStuff now holds a function, you can call it as you would call a normal function.
Please note, the once the IIFE has finished, the variable increaseNumber remains enclosed in its inner scope and is accessible to the function doSomeStuff. This inner scope doesn't get destroyed for the lifetime of doSomeStuff, which is now assigned to doStuff; This is why calling doStuff() leads to the desired effect, i.e. console.log outputs a number increment every time the function gets executed.
Q2 (rephrased): "Why can't I call doStuff as a function?"
var doStuff = (function () {
var increaseNumber = 0;
function doSomeStuff() {
console.log(++increaseNumber);
}
return doSomeStuff();
})();
doStuff();
A2: Again, let's break it down to better understand what happens under the hood.
The variable doStuff is declared.
When the IIFE runs, is calls the function doSomeStuff. Since doSomeStuff does not explicitly return anything, the JavaScript engine assumes it returns undefined. So doStuff now holds a value of undefined.
Since undefined is not a function and is therefore not callable, you will get a runtime error uncaught TypeError: doStuff is not a function.
Hope it helps.

Related

Basic Closure Example Confusion

I'm following a tutorial by Tyler McGinnis on execution contexts, call stacks and closures.
https://www.youtube.com/watch?v=Nt-qa_LlUH0&feature=emb_title
I'm a bit confused with the closure example. I understand a closure is when a function is inside another function. I also understand that the inner function has access to the parent functions arguments (As explained in the video).
My confusion is in the code below is when makeAdder(5) is invoked is the inner function not invoked aswell on the first invokation? Tyler appears to suggest makeAdder is popped off the call stack when first invoked just leaving the inner function untouched.
The second part I don't understand when we call add5(2) this is invoking makeAdder(5) no? How do we add 2 arguments when the parent function only accepts one?
If someone could walk it through step by step of how it's all invoked that would be great!
var count = 0;
function makeAdder(x) {
return function inner(y) {
return x + y;
}
}
var add5 = makeAdder(5);
console.log(add5); // what the call to makeAdder returns
count += add5(2);
console.log(count);
when makeAdder(5) is invoked, is the inner function not invoked as well on the first invocation?
No, it isn't. Only makeAdder is invoked at that time, and makeAdder is not making any calls itself. It merely returns an object, and that object happens to be a function. And returning a function is done without actually invoking it.
when we call add5(2) this is invoking makeAdder(5) no?
It is not invoking makeAdder(5). Earlier on add5 was the result of calling makeAdder(5), and so add5 is that inner function. The special thing happening here is that when you call add5, an "execution context" is restored, which represents the state of affairs inside makeAdder at the moment it returned the function. This practically means that when add5 (the inner function) references the x variable, it will find the value in x it had at the moment makeAdder had been called earlier on.
How do we add 2 arguments when the parent function only accepts one?
Indeed, when we call the parent function, the second argument is not known yet, and we don't need to know it at that moment, since the inner function is not yet executed at that moment. The important thing with the call of the parent function, is that we establish the value of x, which will "live on", even though it can only be accessed by calling the inner function.
And when we call the inner function, we provide the second argument that is needed. The inner function can then combine the "magical" reference it has to the x value (provided when we made the parent call), with the normal argument it receives itself.
A simple way to look at this is as a function that returns a function--which can be called like a normal function because it is. So the first call of the function return type is a function.
Look the following example
function add(x,y){
return x+y;
}
function subtract(x,y) {
return x-y;
}
function calculator(type){
if(type ==='add'){
return add ; //here we are returning a function - the above add function
}
if (type==='subtract')
{
return subtract; // we are returning a function - the above subtract function
}
return null;
}
var fn = calculator('add'); // this call will return the function add which can be called as in below
var result = fn(4,5);
console.log(result) ; ///should print 9
Likewise the first call
var add5 = makeAdder(5);
returns a function which is exactly
function inner(y) { return x+5);
Then you can call add5(2) which essentially execute the above function.

Javascript: how nested functions get variables from parent function

I've read everything about js closures but can't understand the following code:
function main(condition){
var a;
if (condition){
a="aaa";
}
else
{
a="bbb";
return;
}
button.addEventListener("click", function(){ alert(a);});
}
main(true);
main(false);
After that click button. The result is:"aaa". Doest this mean that for nested function doesn't keep the reference to variables but copy them? Please explain.
The first time you run main, you assign "aaa" to a (which is a local variable) and then bind an event handler which reads that variable.
The second time you run main, you assign "bbb" to a (since this is a different invocation of the function, it is a different local variable). You do not bind an event handler that reads that variable since you return first.
When the click event fires, the function it runs is in the scope of the a from the first call, not the second call, so the value is "aaa".
I would say that this is what closures are all about. Closures are "internal functions" that retain access to the values of variables that were "valid" at the moment when the internal function was created even after the "outer function" returned.
Consider the following example:
var outerFunc = function(a) {
return function (x) {
return x+a;
}
} //the outer function returns a function
Now let's invoke the outer function and store the returned value in the variable newFunc:
var newFunc = outerFunc(15); //the outer function has been invoked, newFunc is a function
newFunc(1); //let's invoke the resulting "inner function"
The result will be 16. The inner function will always remember the value 15, even if you invoke the outer function with other argument values. This is how JavaScript works.
In your example with the event listener something very similar is happening. The inner function (with the alert) is registered as a reaction to the click event, and it always 'remembers' the value of a. When you press the button, this invokes this 'inner' function.
To get the behavior you may want, try:
var main = function () {
var a;
return function() {
if (condition){
a="aaa";
}
else
{
a="bbb";
return;
}
button.addEventListener("click", function(){ alert(a);});
};
}();
main(true);
main(false);
This works because it defines a in a way which persists across invocations of the function, which as another answerer pointed out, is the problem.
that is not a closure, its just a double call to a function, when its true it adds the event listener so that it prints 'aaa' but second time it isn't added an event, because it returns before adding it.

How do I read Javascript Closure Syntax?

Based on some code in a lecture by Doug Crockford, I've created this.
var isAlphaUser = (function() {
alert("Forming Alpha User List");
let AlphaUsers = {
1234: true,
5678: true
};
return function(id){
alert("Checking Alpha Users:",id);
return AlphaUsers[id];};
}());
alert("starting");
alert(isAlphaUser(1234));
alert(isAlphaUser(5678));
alert(isAlphaUser(3456));
which gives me this:
Forming Alpha User List
starting
Checking Alpha Users: 1234
true
Checking Alpha Users: 5678
true
Checking Alpha Users: 3456
undefined
Which is quite cool, as it does the expensive setup once only, and every further call is a cheap check.
However, I can't decipher the code that does this. Specifically, I can't understand why I need the "()" at the end of the function declaration.
Can somebody explain how this syntax is working?
() calls a function. function() { } defines a function. Appending () right after immediately calls it1, and the result (also an anonymous function) is assigned to isAlphaUser.
The function() { ... }() pattern is frequently used to isolate variables to an inner scope, so those variables don't become part of the global scope.
In this case, this is what happens:
An anonymous function is run, defining a variable AlphaUsers inside that scope.
That function returns another function that takes 1 parameter. This function is a closure to which the AlphaUsers variable becomes bound (in other words, available). This function checks if the parameter passed in is contained in AlphaUsers (actually, it returns the item at that index, which is just a boolean).
The return value is assigned to a variable isAlphaUser.
Since isAlphaUser is now a function, it can be called to see if the parameter is contained in the AlphaUsers variable, but no direct access to AlphaUsers is available in the global scope (it become a sort of private variable).
1 — Note: As cwolves mentioned in the comments, beware that while () appended directly after the } works in this case, it is only because in this case the function definition is a function expression. If function is the first word on the line, the line becomes a function declaration, and that is all that line can do, the function is not anonymous (it will require a name, otherwise it's a syntax error) and cannot be called immediately inline. See Function Declarations vs. Function Expressions for more info.
The () at the end of the code is separate from the closure issue. By wrapping your function in parens and adding the () at the end you are creating an anonymous function that is run immediately with whatever arguments you pass into ().
Specifically, I can't understand why I need the "()" at the end of the
function declaration.
It creates self-invoking function, in other words, the function is executed as soon as it is parsed.
It is basically same thing when you call a function by suffixing it with () like:
myfunc(); // call this func
The top-level anonymous function returns the function that the isAlphasUser varaible refers to.
You need to call the top-level function, to get the inner-function reference.
Think of it like this, the outer anonymous function is a function factory, i.e., it returns a function.
In order to use any function (even one that returns a function) you must call it.

Javascript closure

The following program returns "local" and, according to the tutorial Im reading, it is designed to demonstrate the phenomenon ofclosure`
What I don`t understand is why, at the end, in order to call parentfunction, it assigns it to the variable "child" and then calls "child."
Why doesn`t it work by just writing parentFunction(); at the end?
var variable = "top-level";
function parentFunction() {
var variable = "local";
function childFunction() {
print(variable);
}
return childFunction;
}
var child = parentFunction();
child();
parentFunction() returns another function which you assign to var child. Then, you call child() to invoke the function returned by the call to parentFunction().
Running just parentFunction(); at the end wouldn't do anything useful because you would just discard its return value which is a function. But this would work:
parentFunction()();
See this fiddle: http://jsfiddle.net/USCjn/
Update: A simpler example:
function outer() { // outer function returns a function
return function() {
alert('inner function called');
}
}
x = outer(); // what is now in x? the inner function
// this is the same as saying:
// x = function() {
// alert('inner function called');
// }
x(); // now the inner function is called
See this fiddle: http://jsfiddle.net/bBqPY/
Functions in JavaScript can return functions (that can return functions (that can return functions ...)). If you have a function that returns another function then it means that when you call the outer function what you get is the inner function but it is not called yet. You have to call the value that you got as a function to actually run the body of the inner function. So:
x = f();
means - run a function f and store what it returns (which may be a string, a number, an object, an array, or a function) in x. But this:
x = f()();
means - run a function f, expect it to return a function and run that returned function as well (the second parentheses) and store in x what the returned function returned.
The function f here is a higher order function because it returns another function. Functions can also take another functions as arguments. One of the most powerful ideas of functional programming languages in general and JavaScript in particular is that functions are just normal values like arrays or numbers that can be returned and passed around.
You have to first grasp the idea of higher order functions to understand closures and the event system in JavaScript.
2016 Update
Note that currently this:
function outer() {
return function() {
alert('inner function called');
}
}
can be written as:
let outer = () => () => alert('inner function called');
using the ES6 arrow function syntax.
The amazing part about closures is that an inner function (in this case, childFunction) can refer to variables outside of its scope (in this case, variable). parentFunction doesn't return the result of childFunction, but an actual reference to the function!
This means that when you do the following...
var child = parentFunction();
...now, child has a reference to childFunction, and childFunction still has access to any variables it had when the function was created, even if they no longer exist.
In order to have parentFunction call childFunction, you'd need to change your code as follows:
From...
return childFunction;
To:
return childFunction();
Douglas Crockford (Pioneer of JSON, among other things) has a whole article devoted to closures, and scoping in javascript, and it would be well worth it to check out his other articles on javascript.
The point that is being demonstrated is that the function that was returned and assigned to child is still referencing the variable that was declared inside parentFunction instead of the one that was declared outside where child() is being invoked.
The only way to create a variable scope in javascript is in a function body. Normally the variable inside the parentFunction would have been discarded after the function returned.
But because you declared a function inside parentFunction that referenced variable in that scope and passed it out of parentFunction, the variable in the parentFunction is retained via the reference made in the new function.
This protects variable from outside manipulation except by functions that closed around it inside parentFunction.

What's the meaning of "()" in a function call?

Now, I usually call a function (that requires no arguments) with () like this:
myFunction(); //there's empty parens
Except in jQuery calls where I can get away with:
$('#foo').bind('click', myFunction); //no parens
Fine. But recently I saw this comment here on SO:
"Consider using setTimeout(monitor, 100); instead of setTimeout('monitor()', 100);. Eval is evil :)"
Yikes! Are we really eval()-ing a string here? I guess I don't really understand the significance and implications of 'calling' a function. What are the real rules about calling and referring to functions?
In JavaScript functions are first-class objects. That means you can pass functions around as parameters to a function, or treat them as variables in general.
Let's say we are talking about a function hello,
function hello() {
alert('yo');
}
When we simply write
hello
we are referring to the function which doesn't execute it's contents. But when we add the parens () after the function name,
hello()
then we are actually calling the function which will alert "yo" on the screen.
The bind method in jQuery accepts the type of event (string) and a function as its arguments. In your example, you are passing the type - "click" and the actual function as an argument.
Have you seen Inception? Consider this contrived example which might make things clearer. Since functions are first-class objects in JavaScript, we can pass and return a function from within a function. So let's create a function that returns a function when invoked, and the returned function also returns another function when invoked.
function reality() {
return function() {
return function() {
alert('in a Limbo');
}
};
}
Here reality is a function, reality() is a function, and reality()() is a function as well. However reality()()() is not a function, but simply undefined as we are not returning a function (we aren't returning anything) from the innermost function.
So for the reality function example, you could have passed any of the following to jQuery's bind.
$('#foo').bind('click', reality);
$('#foo').bind('click', reality());
$('#foo').bind('click', reality()());
Your jQuery bind example is similar to setTimeout(monitor, 100);, you are passing a reference of a function object as an argument.
Passing a string to the setTimeout/setInterval methods should be avoided for the same reasons you should avoid eval and the Function constructor when it is unnecessary.
The code passed as a string will be evaluated and run in the global execution context, which can give you "scope issues", consider the following example:
// a global function
var f = function () {
alert('global');
};
(function () {
// a local function
var f = function() {
alert('local');
};
setTimeout('f()', 100); // will alert "global"
setTimeout(f, 100); // will alert "local"
})();
The first setTimeout call in the above example, will execute the global f function, because the evaluated code has no access to the local lexical scope of the anonymous function.
If you pass the reference of a function object to the setTimeout method -like in the second setTimeout call- the exact same function you refer in the current scope will be executed.
You are not doing the same thing in your jQuery example as in the second setTimeout example - in your code you are passing the function and binding the click event.
In the first setTimout example, the monitor function is passed in and can be invoked directly, in the second, the sting monitor() is passed in and needs to be evaled.
When passing a function around, you use the function name. When invoking it, you need to use the ().
Eval will invoke what is passed in, so a () is required for a successful function invocation.
First of all, "()" is not part of the function name.
It is syntax used to make function calls.
First, you bind a function to an identifier name by either using a function declaration:
function x() {
return "blah";
}
... or by using a function expression:
var x = function() {
return "blah";
};
Now, whenever you want to run this function, you use the parens:
x();
The setTimeout function accepts both and identifier to a function, or a string as the first argument...
setTimeout(x, 1000);
setTimeout("x()", 1000);
If you supply an identifier, then it will get called as a function.
If you supply an string, than it will be evaluated (executed).
The first method (supplying an identifier) is preferred ...

Categories