Skip to content

Instantly share code, notes, and snippets.

@Kos
Created January 18, 2013 20:09
Show Gist options
  • Save Kos/4568081 to your computer and use it in GitHub Desktop.
Save Kos/4568081 to your computer and use it in GitHub Desktop.
This snippet is a piece of trivia that illustrates some behaviour of closures in JS. Remember: With great power comes great responsibility! For details, see my blog post: http://kos.gd/2013/01/closures-the-cute-pets-that-bite/
// This snippet is a piece of trivia that illustrates some behaviour of closures in JS.
// Remember: With great power comes great responsibility!
// For details, see my blog post:
// http://kos.gd/2013/01/closures-the-cute-pets-that-bite/
// Setup
if (typeof(print) === 'undefined') print = console.log.bind(console);
// For starters:
// Here's a function that calculates a sum of every N-th element of a given array.
// It uses a closure as a callback to `forEach`, how many variables are captured in this closure?
function sum_of_every_nth(arr, n) {
var result = 0;
arr.forEach(function(elem, i) {
if (i%n === 0) result += elem;
});
return result;
}
print("Example 1:")
print(sum_of_every_nth([1,100,2,200,3,300,4], 2)); // 10
// Two local variables belong to the closure:
// - n: the parameter
// - result: a local variable defined in the enclosing function.
// Variable n is only read, but result is repeatedly overwritten,
// showing that the closure is able to modify variables in enclosing scope.
// Here's a classic example where a local variable outlives the function call where it's defined in, because a closure uses it:
function makeCounter() {
var counter = 0;
function closure() {
counter += 1;
print(counter);
}
return closure;
}
print("Example 2:")
var c1 = makeCounter();
c1(); // 1
c1(); // 2
var c2 = makeCounter();
c2(); // 1
c1(); // 3
// Each counter is a different function object that has its own copy of the `counter` variable.
// You could capture the same variable inside two different functions:
function makeDoubleCounter() {
var counter = 0;
function addOne() {
counter += 1;
print(counter);
}
function addTen() {
counter += 10;
print(counter);
}
return [addOne, addTen];
}
// Every call to `makeDoubleCounter` creates a new copy of `counter` along with two functions that operate on it.
var a = makeDoubleCounter(),
a_addOne = a[0],
a_addTen = a[1];
a_addOne() // 1
a_addTen() // 11
a_addTen() // 21
var b = makeDoubleCounter(),
b_addOne = b[0]
b_addTen = b[1];
b_addTen() // 10
b_addOne() // 11
a_addOne() // 22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment