Created
January 18, 2013 20:09
-
-
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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