While I was refactoring a code challenge today, I learned something very cool about ES6 variable declarations via the let keyword vs. variable declarations via the var keyword. let is scoped to the nearest block while var is scoped to the nearest function. This is particularly important in the context of loops because let will create a new binding of a variable for each iteration; var will only create one binding.
Let’s take a look at how this informed the refactoring of my code.
The input consists of a 2D array of CSS styles, where each array has a time delay and any number of style objects.
To implement the animator, I looped over the input and set timers to update the style of an element in the DOM after a delay. let‘s block scope binding allowed me to refactor my code without a closure.
An integral part of the challenge is that each step is relative to the previous step. So it’s not enough to apply the styles at step 2 after 200 milliseconds (see input array above); step 2 must be applied after delay + delaySoFar milliseconds, or 300 milliseconds. Likewise, step 3 must be applied after 500 milliseconds.
To persist the cumulative delay, on line 29 above, I declare the variable delaySoFar outside of the loop. Inside of the loop, I set each step’s delay to the sum of the current delay (sequence) and delaySoFar. On line 36, I invoke setTimeOut(), without a closure thanks to let‘s block scope binding. Inside each timer, I set the style of an element in the DOM after the current delay. Last, after the timer is set but before the next loop, I update delaySoFar. The result animates the element and each step’s delay is relative to the previous step.
I really enjoyed this code challenge. The efficiency of let‘s block scoping is nifty.