Closure is confusing yet again , please help!

Closure is confusing yet again , please help!
0

#1

Hi,

So i was thinking well now i have a good idea of what closure is, just an inner function having access to values of the outer function kept alive …

Now i came across a simple exercise, keep the value of a variable incremented by one each time a function is called , i tried …Every time the value is 0 or 1, is there no way to achieve it with out some super complex closure , … they are asking me to try some thing like this — But i have no clue why this works and others do not, so is there no other way to achieve this with out closures? Kindly guide

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

WORKS


function add() {
   var counter = 0;
    function plus() {
        counter++;
    }
    
    plus();
    return counter;
}

FAILED

function add() {
   var counter = 0;
    function plus() {
        counter++;
    }
    
    plus();
    return counter;
}

FAILED


function add() {
    var counter = 0;
    counter++;
    return counter;
}

FAILED

PS - In the end all is want is increment the value of a variable each time a function is called


#2

Boss, I don’t get 0. First one is a closure. You can keep incrementing it by calling add(); The others aren’t, they will return 1 always.


#3

@dahis39 - If one were to call

add()
add()
add()

The total should be 3 ?

Is it working at your end , how is possible , not working on my chrome


#4

I think you are mixing constructors and closures.

Constructors is a way to define “objects” that holds values and methods, and can be assigned and manipulated.
To make your example work by defining a add constructor I would:

function add() {
   this.counter = 0;
   this.add = function() { return this.counter++ };
   this.print = function() { return this.counter};
}

const c = new add();
c.add();
c.add();
c.print() // 2

A closure however is a function inside the scope of another function.
It’s important to notice that in JS the inner function maintains the reference of the local variables when it was created.
In many other languages those local variables are “forgotten” once the function has finished running.

This means that I can use closure to compose functions like in this example from MDN

// a function that returns a function
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

// here makeAdder is waiting for y to be passed, but x is init as 5
var add5 = makeAdder(5);

// here makeAdder is waiting for y to be passed, but x is init as 10
var add10 = makeAdder(10); 

// now I can call my closure with the ease that they'll "remember" 
// the scope they had once called:
add5(2) // 7 --> 5 + 2
add10(5) //15 --> 10 + 5

Note that the reason your example works is because it’s an immediately invoked function meaning that is calling the returning function without explicitly telling them to do so; like in the MDN example above where I had to pass also the second argument
:slight_smile:

Hope it helps :+1:


#5

@Marmiz - thanks a lot, but my mind is a bit stuck on this idea that is there a way i can create a function with out using closure that after creating it i can just call -

add() and it will add one to counter and not be reset to 0 …

I understand the closure part you explained but i was thinking if it is possible with out closure and constructor

Also just one more point if the function was not to be IIFE will there be no way to achieve this …

… thanks


#6

If you use a global variable instead it should work, but it will also clutter the global namespace.


#7

With the usage of a normal function a global (or at least outside of the function scope) variable will do with ease:

var count = 0;

function add() {
  // do magical stuff then update the counter
  count++;
  console.log(count)
}

But I thought the question was about closures :slight_smile:


Also just one more point if the function was not to be IIFE will there be no way to achieve this …

Of course there is, you just have to actually call the returning function “manually” instead of expecting it to do it for you:

var add = function () {
    var counter = 0;
    return function () {return counter += 1;}
};

const a = add()
a() //1
a() // 2
a() // 3

#8

No. Don’t use a global variable. It’s cheating :slight_smile:
You’re seriously better off without them - global variables are a ‘code smell’ imo.

The first example you gave is an example of a closure -

var add = (function () {
    var counter = 0;
    return function () {
      console.log(`counter was ${counter}, now it's ${counter + 1}`)
      return counter += 1;
    }
})();

add() // prints 'counter was 0, now it's 1'
add() // prints 'counter was 1, now it's 2'
add() // prints 'counter was 2, now it's 3'

The top part basically looks like this

var add = (function () {...stuff...})();

It’s defining a function (that doesn’t have a name) and assigning it to add.

Except it isn’t, because the function is getting invoked also - the last pair of brackets make that happen - so what it assigns to the variable ‘add’ is whatever the function returns. (this is called an “immediately invoked function expression” or IIFE)

What does the function return? It returns another function.

return function () {return counter += 1;}

which means that ‘add’ is now a function that can be called. The function stored there is

return counter += 1

We call this a closure and say that the function has closed over the variables that it refers to. Notice that this function doesn’t declare the variable it uses.

The function that created it declared the variable ‘counter’ - it’s already been destroyed and it doesn’t even have a name but it doesn’t matter because this new function took the variables it needs with it.