There is a pattern in JavaScript that we use all the time without noticing it: Closure!
A closure occurs when you use an outer variable in an inner block. Here is a simple example:
let count = 0;
function increment() {
count++; // closure here!
return count;
}
increment();
console.log(count); //==> 1
Closures can come in handy when you want to save a function’s state.
Say that you’re building a video game, and you have a function that applies teleportation to a given object in a 2D context:
function teleport(object, x, y) {
object.x = x;
object.y = y;
}
You want to be able to teleport objects in your game. But the possible amount of teleportation can vary. What you can do is create a function that returns a new function limiting the amount of time we call the teleport
function:
function teleportNTime(n) {
let count = 0;
return function (object, x, y) {
if (count === n) {
console.log("can't teleport anymore!");
return;
}
teleport(object, x, y);
count++;
console.log('count: ', count);
};
}
const teleport2Time = teleportNTime(2);
const teleport3Time = teleportNTime(3);
Two variables represent the state of teleport2Time
:
- the argument we passed
teleportNTime
; which isn = 2
. - the
count
variable
Here the state is saved because each time we teleport, we remember the count and the teleportation limit (n = 2
).
const goku = { name: 'goku', x: 0, y: 0 };
teleport2Time(goku, 2, 4); //=> count: 1
teleport2Time(goku, 8, 10); //=> count: 2
teleport2Time(goku, 0, 0); //=> can't teleport anymore!
Notice that the state of teleport3Time
is independent of teleport2Time
.
teleport3Time(goku, 2, 4); //=> count: 1