Variable evaluation and race conditions
Suppose we have some code like this:
// elementsArray is an array of 10 jQuery objects
for (let i = 0; i < elementsArray.length; i++) {
let elementID = elementsArray[i].attr("id");
// Fade in the element over 400ms.
$(`#${elementID}`).fadeIn(400, function () {
// Once elementID is faded in, fade in its child element with the ID `elementID`-child over 1000ms.
$(`#${elementID}-child`).fadeIn(1000);
});
}
Expected Result
Each element is faded in over 400ms, and when each fade in completes, the element's child is faded in by the complete function.
Actual Result
Only one child element is faded in - the last one.
The problem and how to fix it
In this code, we loop over ten elements, instruct jQuery to fade in each one, and tell it that once each fade in completes, the child element for that element should be faded in as well. The problem is due to how we have assigned the elementID variable.
When using the let declaration, we are not assigning a constant value to elementID. Once jQuery's 400ms fade in has finished, and the function is called to fade in the child element, our for loop has finished and the value of elementID is set to the final element in the array.
If we use the const declaration, this problem is avoided, as now each version of elementID in the for loop is immutable and does not change.
// elementsArray is an array of 10 jQuery objects
for (let i = 0; i < elementsArray.length; i++) {
const elementID = elementsArray[i].attr("id");
// Fade in the element over 400ms.
$(`#${elementID}`).fadeIn(400, function () {
// Once elementID is faded in, fade in its child element with the ID `elementID`-child over 1000ms.
$(`#${elementID}-child`).fadeIn(1000);
});
}