Toggle
EasyPrompt
Write a function called createToggle that takes multiple values and returns a new function. When called, this new function should return each value in sequence, cycling back to the beginning after reaching the end.
Requirements
- Accept any number of input values
- Return a function that cycles through these values
- Each call to the returned function gives the next value in sequence
- After the last value, it should start over from the first
Example
const colorToggle = createToggle('red', 'green', 'blue');
colorToggle(); // returns 'red'
colorToggle(); // returns 'green'
colorToggle(); // returns 'blue'
colorToggle(); // returns 'red' (cycles back to beginning)
const toggle = createToggle('on', 'off');
toggle(); // returns 'on'
toggle(); // returns 'off'
toggle(); // returns 'on' (cycles back to beginning)
const singleToggle = createToggle('always');
singleToggle(); // returns 'always'
singleToggle(); // returns 'always' (cycles back to beginning)
Playground
Closure is your friend! Remember that JavaScript functions can "remember" variables from their outer scope. This lets you keep track of state between function calls without using global variables.
Modulo is the cycling magic. Think about what happens when you add 1 to a number and then apply the modulo operator with the length of your array. This elegant little trick can create an endless cycle that never goes out of bounds!
Solution
Explanation
The createToggle
function is a clever utility that creates a stateful cycling mechanism. It's a practical tool for managing rotations through states, values, or options in your applications - from toggling themes to opening or closing elements like modals.
Let's look at how our code is working, we will break it down step by step.
- Takes any number of values as parameters (using the rest parameter
...values
) - Creates a closure that maintains the current position in the cycle
- Returns a new function that, when called, gives the next value in the sequence
function createToggle(...values) {
if (values.length === 0) {
throw new Error('At least one value must be provided');
}
let index = 0;
return () => {
const currentValue = values[index];
index = (index + 1) % values.length;
return currentValue;
};
}
This elegant solution works through these key mechanisms:
-
Closure: The
index
variable is enclosed in the returned function, maintaining its state between function calls. -
Rest Parameters: The
...values
syntax collects all arguments into an array, allowing our toggle to accept any number of values. -
Modulo Operator: The expression
(index + 1) % values.length
is the cycling magic. It increments the index by 1, then divides by the array length and returns the remainder. This cleverly wraps the index back to 0 when it reaches the end.
For example, when we create const colorToggle = createToggle('red', 'green', 'blue')
:
- The first call returns 'red' and sets index to 1
- The second call returns 'green' and sets index to 2
- The third call returns 'blue' and sets index to 0 (because 3 % 3 = 0)
- The fourth call returns 'red' again, starting the cycle over
The toggle pattern is commonly used in UI development for features like opening or closing elements like modals.
Resources
MDN Web Docs: Closures