Closures: How does this specific piece work? [duplicate] - javascript

This question already has answers here:
How do JavaScript closures work?
(86 answers)
Closed 8 years ago.
I'm struggling with this concept. By looking at below, I don't understand when I type on the console that "counter" is equal to the following below. How does it know just to pick up this piece of the code? How does this work?
function(val) {
count += val;
return console.log(count);
};
The Code
var incrementer = function(initialValue) {
var count = initialValue;
return function(val) {
count += val;
return console.log(count);
};
};
var counter = incrementer(5);
counter(3);
counter(1);

Because incrementer returns a function, this effectively means that once counter is filled with incrementer(5) it then becomes a reference to the function that is returned by incrementer this means that the counter variable looks something like this at that time:
counter = function(val) {
count += val;
return console.log(count);
};
To verify this:
console.log(counter);
Therefore subsequent calls to counter will increment the value of count
Note: the variable count exists within the scope of incrementer and can be accessed only because the function that counter refers to was created within that scope.

Incrementer is a function that returns a function. counter is equal to the return of the incrementer function which is a function that takes in a value and increments the value you initially passed in incrementer(5).
Calling incrementer(5) sets the initial state intrinsically, but returns the function that you can invoke with the counter pointer (variable) you created.
Does that explanation make sense?
var counter = incrementer(5); //initializes the "initial value" and returns a function, thus setting "counter" equal to a function.. aka function pointer
counter(3); //invokes the function that increments the value by 3 - hence 8

In javascript , a function remembers the context in which it has been declared.
That the quickest way to explain closures.
So if you create a function that returns a function, the returned functions will "close" on the variables of the outer function, thus the returned function having states.
Since count has been declared in the "parent" scope of the returned function, the returned function will remember that its internal variable count refers to the variable count of incrementer .

Related

Hoisting inside function having same variable name [duplicate]

This question already has answers here:
Variables with the same name, but the local scope variable isn't being used, why?
(4 answers)
Closed 3 years ago.
So I thought I understood hoisting in JavaScript until I saw something like this:
function hoist(a) {
console.log(a);
var a = 10;
}
hoist(5);
The code above outputs 5, not undefined!
As per my understanding, the function looks like this to the interpreter:
function hoist(a) {
var a; // This should overshadow the parameter 'a' and 'undefined' should be assigned to it
console.log(a); // so this should print undefined
a = 10; // now a is assigned 10
}
So what's happening here?
You would be right if the var was called b, but the var a already exists. redeclaring a javascript variable that already exists doesn't do anything. It will not change the value to undefined. Try it.
function hoist(a) {
var a; // no op, does not change a to undefined.
console.log(a);
a = 10;
}
hoist(18);
This falls back in the section Only declarations are hoisted in the MDN (to link some documentation, at least).
The second example given there is the exact one you're looking for:
num = 6;
console.log(num); // returns 6
var num; // or, really, var num = whatever.
To just recall what is said:
If you declare the variable after it is used, but initialize it beforehand, it will return the value.
Hoisting a variable means that the variable name is known to the compiler from the beginning of the block. It does not re-introduce, overwrite, clear or reset the variable if it already exists.
Until something is assigned, the value of that variable is undefined, but hoisting itself does nothing to the value of the variable.
It so happens that a function parameter is also a way of declaring a variable, like an invisible var statement, followed by an assignment that happens as the function gets called, before any of the actual function body executes.
Hoisting is still working as we expect, as we can see that the following snippet also outputs 5:
function hoist(a) {
var a;
console.log(a);
a = 10;
}
hoist(5);
What we really have here is a function parameter, a, being redeclared inside the function where its value has already been initialized to 5.
you are correct that hoisting would work this way inside of that function.
In this particular example we pass an argument/parameter to our function and it changes how it will be interpreted. Just take a look:
function hoist(a) { // here's our 'a' parameter gets replaced by '5' that we passed while execution of this function
var a; // with no new value it does nothing
console.log(a); // so this will print 5 that we passed to this function
a = 10; // now a is assigned 10 and next console.log() would show a new value of 'a' variable
}
Hoisting has to do with calling a function before it is declared, as javascript will push the function declarations to the top. The parameter a and the variable a don't related to hoisting in this case.

What is the lifetime of variables inside a self calling function in javascript

I've been trying to understand the following code:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
Here add is assigned the return value of the anonymous self calling function -- that is the function function() { return counter += 1 }. Now the first time add() is called it returns 1 as expected. But the second time add() is called it returns 2.
My question is since counter is defined inside a function so wouldn't every time the function finishes execution counter should die? That is, after the first call to add() 1 will be displayed. Now we are out of that function so shouldn't counter forget it's previous value and be destroyed from the stack like automatic variables are?
What is the lifetime of variables inside a self calling function in javascript
The same as variables in any other kind of JavaScript function: They exist for as long as they can be referenced, which sometimes means long past the time the function that contains them returns.
Your counter variable continues to exist after the IIFE returns because the function it creates and returns (return function () {return counter += 1;}) is a closure over the variable. The variable will exist as long as that function exists.
More technically: Calling a function creates something called an execution context for that call, which has a variable enviroment object. Any function created during the call receives a reference to that outer variable environment object; that object, like all objects, exists as long as there's a reference to it, and so the functions keep the object alive. Variables are actually properties of that variable environment object, and so they exist as long as something references the object they're on. (This is the very simplified form.) While in theory the entire variable environment object is kept, in practice JavaScript engines are free to optimize if the effects of optimization aren't observable, so a variable that isn't actually used by the closure may (or may not) be released, depending on the engine and the code in the function.
Your IIFE can only be called once, so there can only be one counter, but it's common for a function creating a closure to be called more than once, in which case you have multiple variable objects, and multiple copies of the variables that are closed over.
Example:
function helloBuilder(name) {
var counter = 0;
return function() {
++counter;
display("Hi there, " + name + ", this is greeting #" + counter);
};
}
var helloFred = helloBuilder("Fred");
var helloMaria = helloBuilder("Maria");
helloFred(); // "Hi there, Fred, this is greeting #1"
helloFred(); // "Hi there, Fred, this is greeting #2"
helloMaria(); // "Hi there, Maria, this is greeting #1"
helloMaria(); // "Hi there, Maria, this is greeting #2"
helloFred(); // "Hi there, Fred, this is greeting #3"
function display(msg) {
var p = document.createElement('p');
p.appendChild(document.createTextNode(msg));
document.body.appendChild(p);
}
In the above, the function returned by helloBuilder closes over both its name argument and its counter variable. (Because arguments are also stored on the execution context's variable object.) So we can see that after calling it twice, there are two variable objects, each with its own name and counter, one referenced by each function we asked helloBuilder to create.

Why am I getting two different results from two functions that don't seem different at all taking advantage of closures?

I've assigned the number 0 to a variable outside of a function. I'm using this variable to take advantage of closures because I've also created a simple function that returns the variable incremented solely for the purpose of keeping track of how many times I call the function. I call the function 5 times and finally pass the function invoked to the alert function. What's confusing is, if I increment the variable and then return the variable afterward, the alert message I get is "6" rather than "5" which is the number of times I called the function however, if I increment the variable and return it at the same time, meaning the variable incrementation is a part of the return statement, I get the correct number of times I've called the function in the alert message. Why am I getting different results? The variable outside of the function I'm using as my counter is assigned the number 0. The global execution context is created and holds this variable right? In addition to that, my 5 calls have created 5 execution contexts and each time, the new incremented variable lives and stays in memory for the next call to increment. Where is "6" coming from?
Here's my code that produces 6 as the number of times the function has been called:
var i = 0;
function add() {
i++;
return i;
}
add();
add();
add();
add();
add();
alert(add());
By simply doing this:
function add() {
return i++;
}
I get the correct number alerted.
In first case value is returned after incrementing, in second value is returned before incrementing
try alert ( i ); rather than alert( add() ); you will get the same value
That's related to incrementing flow.
Pre-increment (++i) adds one to the value of i, then returns i, in contrast, i++ returns i then adds one to it.
In first case you increment value in separate statement so, pre or post increment doesn't play any role, in second pre or post incrementation play role, because function firstly return i and than increment.
You would get same result in case if your function add would be the next
function add(){
return ++i;
}
return i++; means you return i first and then do the increment.
By the way,
return ++i; means you do the incrementfirst and then return i.
When you are calling alert(add()), you are calling add() one more time and henece the value of i increment to 6 since current value of i is 5 as you have already called add 5 times. If you print i before add() call in alert its still 5 but as soon as you call add() in alert it becomes 6 because you are invoking method call.
var i = 0;
function add() {
i++;
return i;
}
add();
add();
add();
add();
add();
// alert(i +' '+ add()); //5 6
alert(add() +' '+ i); //6 6

Passing variable as argument in closure

I'm studying closures and found the following example code for incrementing a "private" variable named count:
function setup() {
var count = 0;
return function() {
count += 1;
console.log(count);
}
};
var next = setup();
next();
This makes sense to me. However, when I experimented with passing the variable as an argument to the nested function, next() logs 'NaN' to the console. Eg:
function setup() {
var count = 0;
return function(count) {
count += 1;
console.log(count);
}
};
var next = setup();
next();
Can someone explain why this happens?
Can someone explain why this happens?
Inside the closure, count now refers to the parameter, function(count) {. Since you are not passing any argument when you call the function, count is undefined and adding a number to undefined results in NaN.
when I experimented with passing the variable as an argument to the nested function
To be clear: The count parameter has nothing to do with the count variable defined in the outer function. You are not passing the variable as argument, because you are not calling the function, you are defining it.
It's because the inner function now has access to a more local variable, so it doesn't look at any closures it has access to for the "count" variable. And nothing is passed, so count is undefined.
This answer may be useful: Scope Chain in Javascript

Do, inner and outer functions get their own copy of same variable?

just a bit confused by this code
var counter = function() {
//...
var count = 0;
return function () {
return count = count + 1;
}
}
var nextValue = counter();
console.log(nextValue());
nextValue.count = 7;
console.log(nextValue());
console.log(nextValue.count);
console.log(nextValue());
Output is
1
2
7
3
It's counter intuitive. There are two representations of count. One on the outerfunction nextValue and one that only the inner anonymous function can see.
Correct, or are my missing something?
The expression nextValue.count does not refer to the local variable "count" declared inside the function. It is not possible, in fact, to create a reference to a variable local to a function from code outside the function. What you're referencing there is simply a property of the function object.
So, yes, the "count" variable that the returned function has access to is effectively completely private to that function, and it is persisted in the closure formed by the call to the "counter" function.
If you did want that to work, you could do this:
function counter() {
function actual() {
return actual.count = actual.count + 1;
}
actual.count = 0;
return actual;
}
edit — (fixed bogus code) the name "actual" inside gives the returned function safe access to the function object itself; originally I typed "this" there, and that would not work unless the external code set it up explicitly.
The way you describe it, count is effectively a private variable. When you're assign to nextValue.count, you're creating a separate property--not accessing the internal count being incremented by your counter.

Categories

Resources