double loop applying only to the last item of the array

Viewed 662

recently started re-doing an online course WDB2.0 on Udemy.

The objective was to make each letter from array of letters RAINBOW coloured according to rainbow colors using javascript selector.

const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']; html code : https://pastebin.com/uDAA1UaP

I have managed to complete the exercise by writting the following code:

const rainbow= document.querySelectorAll("span");
for (let letter of rainbow){
    letter.style.color=colors[0];
    colors.shift() 
}

My question is why did none of the following codes worked? Both of them have colored the whole text in violet, rather than each letter according to the index of the colors array: 1)

for (let i = 0; i<colors.length; i++){
    for(let letter of rainbow){
        letter.style.color=colors[i]
    }
}
for (let letter of rainbow){
    for(let i = 0; i<colors.length; i++){
        letter.style.color=colors[i]
    }
}

I have always struggled with double loops and would really appreciate if you could explain what am I doing incorrectly.

Many thanks!

4 Answers
  1. Your code first rendered all the letters red, then all the letters orange e.t.c, then all the letters violet because you have a loop in an another loop. For each color it paints all the letters using the inner for loop, iterating through them.

  2. The same problem here, but it takes each letter and paints it with all the colors, ending in violet. For each letter you take all the colors.

Here's a decent approach. A couple of thoughts in the comments

const rainbow = document.querySelectorAll("span");
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];

for (let i = 0; i < rainbow.length; i++) { // use the length of rainbow because we want all spans to have a color
  rainbow[i].style.color = colors[i % colors.length]; // cycle through colors if there are more elements in rainbow than in colors
}
    <h1>
        <span>R</span>
        <span>A</span>
        <span>I</span>
        <span>N</span>
        <span>B</span>
        <span>O</span>
        <span>W</span>
        <span>R</span>
        <span>A</span>        
    </h1>

To understand things on your own use

console.log(i)
console.log(colors[i])

in the inner for loop. After the inner loop and before the end of the outer loop add :

console.log()  // This will create a new line and makes debugging the output easy. 

Once you have understood what is happening with the loops you can debug things easily later on for different kinds of double loops also.

Case 1 : When the last outer loop is running i = colors.length - 1. This means violet color is being used. The inner loop iterates over all the letters in the word rainbow and hence all the words end up with the color violet.

Case 2: The first time when the outer loop runs the letter r is considered. But the inner loop iterates over all the colors from red to violet, since the last color is violet, letter r is assigned the color violet.

The second time when the outer loop runs the letter a is considered. But the inner loop iterates over all the colors from red to violet, since the last color is violet, letter a is assigned the color violet. . . . . . . The last time when the outer loop runs the letter w is considered. But the inner loop iterates over all the colors from red to violet, since the last color is violet, letter w is assigned the color violet.

Whenever you are stuck with loops use print statements to debug what is happening with the logic.

Const spans = document.querySelectorAll('span');
        for(let i=0; i<=colors.length ; i++){
              spans[i].style.color = colors[i];
        } 
Related