Skip to content

Instantly share code, notes, and snippets.

@turboza
Last active October 3, 2016 05:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save turboza/207c4806595db79952af62eda2005d14 to your computer and use it in GitHub Desktop.
Save turboza/207c4806595db79952af62eda2005d14 to your computer and use it in GitHub Desktop.
Closure gotcha
/*
* This code snippet give an unexpected result because the closure (function inside function)
* that will preserve the local variable "i" eventhough buildAction is finished
* So every action in array will refer to the same "i" which is 4 after finishing loop.
*
* Result :(
* ```
* "item 4 = undefined"
* "item 4 = undefined"
* "item 4 = undefined"
* "item 4 = undefined"
* ```
*/
function buildActions(list) {
var actions = [];
for (var i=0; i<list.length; i++) {
actions.push(() => {
console.log(`item ${i} = ${list[i]}`)
});
}
return actions;
}
var list = [9, 10, 11, 12];
var actions = buildActions(list);
actions.forEach(action => action());
/*
* This code snippet is a fix from closure-issue.js with 1 thing change from var i --> let i (ES2015)
* Because let/const will only exist in the { } scope, let i will create new i for every iteration.
*
* Result :)
* ```
* "item 0 = 9"
* "item 1 = 10"
* "item 2 = 11"
* "item 3 = 12"
* ```
*/
function buildActions(list) {
var actions = [];
for (let i=0; i<list.length; i++) { // <--- Just change var to let here
actions.push(() => {
console.log(`item ${i} = ${list[i]}`)
});
}
return actions;
}
var list = [9, 10, 11, 12];
var actions = buildActions(list);
actions.forEach(action => action());
/*
* Look more closely on transpiled version with babel for how it's fixed in ES5
* ref: https://babeljs.io/repl (You can paste the ES2015+ code to see how it is transpiled)
*/
"use strict";
function buildActions(list) {
var actions = [];
var _loop = function _loop(i) {
actions.push(function () {
console.log("item " + i + " = " + list[i]);
});
};
for (var i = 0; i < list.length; i++) {
_loop(i);
}
return actions;
}
var list = [9, 10, 11, 12];
var actions = buildActions(list);
actions.forEach(function (action) {
return action();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment