Hearen
Hearen

Reputation: 7828

Javascript Closure is not working?

I know this seems silly. But just now I tried to test the closure in JS.

var funcList = [];
for(let i = 0; i < 3; ++i) {
  funcList.push(() => { console.log(i); });
}
console.log('testing for reference');
funcList.forEach(func => func());

funcList.length = 0;
for(let i = 0; i < 3; ++i) {
  funcList.push(
  ((i) => { 
    return () => { console.log(i); }
  })()
  );
}
console.log('testing for no reference');
funcList.forEach(func => func());

But unluckily, I encountered issues as follows:

The expected output should be (at least I thought ~~, highly possible fact is I'm wrong):

testing for reference
3
3
3
testing for no reference
0
1
2

But it gave me

testing for reference
0
1
2
testing for no reference
undefined
undefined
undefined

What is happening out here? Can anyone shed the light upon me?

Thank you so much for any possible helpful advice.

UPDATE 2018-3-24 Thanks for @Patrick Evans It's working as follows now:

var funcList = [];
for(var i = 0; i < 3; ++i) { // using var instead of let
  funcList.push(() => { console.log(i); });
}
console.log('testing for reference');
funcList.forEach(func => func());

funcList.length = 0;
for(var i = 0; i < 3; ++i) {
  funcList.push(
  ((i) => { 
    return () => { console.log(i); }
  })(i) // pass in the `i`
  );
}
console.log('testing for no reference');
funcList.forEach(func => func());

Updated 2018-03-30

A real closure should be

var funcList = [];
(function () {
    let i = 0;
    while (i++ < 3) {
        funcList.push(() => { console.log(i); });
    }
})();
console.log('testing for reference');
funcList.forEach(func => func());

Upvotes: 1

Views: 292

Answers (1)

Vasan
Vasan

Reputation: 4956

You forgot to pass i's value to the function, which is expecting a parameter. Since parameter doesn't have a value it logs undefined. Try this:

funcList.push(
  ((i) => { 
    return () => { console.log(i); }
  })(i) //Pass i's value as param
  );

Upvotes: 3

Related Questions