|
| 1 | +///// Loops: while and for |
| 2 | + |
| 3 | +/* |
| 4 | + We often need to repeat actions. |
| 5 | + Loops are a way to repeat the same code multiple times. |
| 6 | + */ |
| 7 | + |
| 8 | +///// The “while” loop |
| 9 | + |
| 10 | +// The while loop has the following syntax: |
| 11 | + |
| 12 | +while (condition) { |
| 13 | + // code |
| 14 | + // so-called "loop body" |
| 15 | +} |
| 16 | + |
| 17 | +// While the condition is truthy, the code from the loop body is executed. |
| 18 | + |
| 19 | +// For instance, the loop below outputs i while i < 3: |
| 20 | +let i = 0; |
| 21 | +while (i < 3) { // shows 0, then 1, then 2 |
| 22 | + console.log(i); |
| 23 | + i++; |
| 24 | +} |
| 25 | + |
| 26 | +// A single execution of the loop body is called an iteration. The loop in the example above makes three iterations. |
| 27 | + |
| 28 | +// If i++ was missing from the example above, the loop would repeat (in theory) forever. In practice, the browser provides ways to stop such loops, and in server-side JavaScript, we can kill the process. |
| 29 | + |
| 30 | +// Any expression or variable can be a loop condition, not just comparisons: the condition is evaluated and converted to a boolean by while. |
| 31 | + |
| 32 | +// For instance, a shorter way to write while (i != 0) is while (i): |
| 33 | +let index = 3; |
| 34 | +while (index) { // when i becomes 0, the condition becomes falsy, and the loop stops |
| 35 | + console.log(index); |
| 36 | + index--; |
| 37 | +} |
| 38 | + |
| 39 | +// Curly braces are not required for a single-line body |
| 40 | +// If the loop body has a single statement, we can omit the curly braces {…}: |
| 41 | +while (index) console.log(i--); |
| 42 | + |
| 43 | + |
| 44 | +///// The “do…while” loop |
| 45 | + |
| 46 | +// The condition check can be moved below the loop body using the do..while syntax: |
| 47 | + |
| 48 | +do { |
| 49 | + // loop body |
| 50 | +} while (condition); |
| 51 | + |
| 52 | +// The loop will first execute the body, then check the condition, and, while it’s truthy, execute it again and again. |
| 53 | + |
| 54 | +let value = 0; |
| 55 | +do { |
| 56 | + console.log(value); |
| 57 | + value++; |
| 58 | +} while (value < 3); |
| 59 | + |
| 60 | +// This form of syntax should only be used when you want the body of the loop to execute at least once regardless of the condition being truthy. Usually, the other form is preferred: while(…) {…}. |
| 61 | + |
| 62 | +///// The “for” loop |
| 63 | + |
| 64 | +// The for loop is more complex, but it’s also the most commonly used loop. |
| 65 | + |
| 66 | +// The “for” loop syntax: |
| 67 | +for (begin; condition; step) { |
| 68 | + // ... loop body ... |
| 69 | +} |
| 70 | + |
| 71 | +// Let’s learn the meaning of these parts by example.The loop below runs console.log(i) for i from 0 up to(but not including) 3: |
| 72 | + |
| 73 | +for (let i = 0; i < 3; i++) { // shows 0, then 1, then 2 |
| 74 | + console.log(i); |
| 75 | +} |
| 76 | + |
| 77 | +/* |
| 78 | + Let’s examine the for statement part-by-part: |
| 79 | +
|
| 80 | + begin let i = 0 Executes once upon entering the loop. |
| 81 | + condition i < 3 Checked before every loop iteration. If false, the loop stops. |
| 82 | + body console.log(i) Runs again and again while the condition is truthy. |
| 83 | + step i++ Executes after the body on each iteration. |
| 84 | +
|
| 85 | +*/ |
| 86 | + |
| 87 | +// Inline variable declaration |
| 88 | +// Here, the “counter” variable i is declared right in the loop. This is called an “inline” variable declaration. Such variables are visible only inside the loop. |
| 89 | + |
| 90 | +// Instead of defining a variable, we could use an existing one: |
| 91 | + |
| 92 | +for (let i = 0; i < 3; i++) { |
| 93 | + console.log(i); // 0, 1, 2 |
| 94 | +} |
| 95 | +console.log(i); // error, no such variable |
| 96 | + |
| 97 | +// Skipping parts |
| 98 | + |
| 99 | +// Any part of for can be skipped. |
| 100 | + |
| 101 | +// For example, we can omit begin if we don’t need to do anything at the loop start. |
| 102 | + |
| 103 | +for (; i < 3; i++) { // no need for "begin" |
| 104 | + console.log(i); // 0, 1, 2 |
| 105 | +} |
| 106 | + |
| 107 | +// We can also remove the step part: |
| 108 | + |
| 109 | +for (; i < 3;) { |
| 110 | + console.log(i++); |
| 111 | +} |
| 112 | + |
| 113 | +// We can actually remove everything, creating an infinite loop: |
| 114 | + |
| 115 | +/* |
| 116 | +for (; ;) { |
| 117 | + // repeats without limits |
| 118 | + } |
| 119 | + */ |
| 120 | + |
| 121 | + |
| 122 | +///// Breaking the loop |
| 123 | + |
| 124 | +// Normally, a loop exits when its condition becomes falsy. |
| 125 | + |
| 126 | +// But we can force the exit at any time using the special break directive. |
| 127 | + |
| 128 | +let sum = 0; |
| 129 | + |
| 130 | +while (true) { |
| 131 | + |
| 132 | + let value = +prompt("Enter a number", ''); |
| 133 | + |
| 134 | + if (!value) break; // (*) |
| 135 | + |
| 136 | + sum += value; |
| 137 | + |
| 138 | +} |
| 139 | +alert('Sum: ' + sum); |
| 140 | + |
| 141 | +// The break directive is activated at the line (*) if the user enters an empty line or cancels the input. It stops the loop immediately, passing control to the first line after the loop. Namely, alert. |
| 142 | + |
| 143 | +///// Continue to the next iteration |
| 144 | + |
| 145 | +// The continue directive is a “lighter version” of break. It doesn’t stop the whole loop. Instead, it stops the current iteration and forces the loop to start a new one (if the condition allows). |
| 146 | + |
| 147 | +for (let i = 0; i < 10; i++) { |
| 148 | + |
| 149 | + // if true, skip the remaining part of the body |
| 150 | + if (i % 2 == 0) continue; |
| 151 | + |
| 152 | + alert(i); // 1, then 3, 5, 7, 9 |
| 153 | +} |
| 154 | +// The continue directive helps decrease nesting |
| 155 | + |
| 156 | +/* |
| 157 | + No break/continue to the right side of ‘?’ |
| 158 | +
|
| 159 | + Please note that syntax constructs that are not expressions cannot be used with the ternary operator ?. In particular, directives such as break/continue aren’t allowed there. |
| 160 | +*/ |
| 161 | + |
| 162 | + |
| 163 | +///// Labels for break/continue |
| 164 | + |
| 165 | +// Sometimes we need to break out from multiple nested loops at once. |
| 166 | + |
| 167 | +for (let i = 0; i < 3; i++) { |
| 168 | + |
| 169 | + for (let j = 0; j < 3; j++) { |
| 170 | + |
| 171 | + let input = prompt(`Value at coords (${i},${j})`, ''); |
| 172 | + |
| 173 | + // what if we want to exit from here to Done (below)? |
| 174 | + } |
| 175 | +} |
| 176 | + |
| 177 | +alert('Done!'); |
| 178 | + |
| 179 | +/* |
| 180 | + The ordinary break after input would only break the inner loop. That’s not sufficient – labels, come to the rescue! |
| 181 | +
|
| 182 | + A label is an identifier with a colon before a loop: |
| 183 | + labelName: for (...) { |
| 184 | + ... |
| 185 | +} |
| 186 | +*/ |
| 187 | + |
| 188 | +// The break <labelName> statement in the loop below breaks out to the label: |
| 189 | + |
| 190 | +outer: for (let i = 0; i < 3; i++) { |
| 191 | + |
| 192 | + for (let j = 0; j < 3; j++) { |
| 193 | + |
| 194 | + let input = prompt(`Value at coords (${i},${j})`, ''); |
| 195 | + |
| 196 | + // if an empty string or canceled, then break out of both loops |
| 197 | + if (!input) break outer; // (*) |
| 198 | + |
| 199 | + // do something with the value... |
| 200 | + } |
| 201 | +} |
| 202 | + |
| 203 | +alert('Done!'); |
| 204 | + |
| 205 | + |
| 206 | +/// Summary |
| 207 | + |
| 208 | +/* |
| 209 | + We covered 3 types of loops: |
| 210 | +
|
| 211 | + while – The condition is checked before each iteration. |
| 212 | + do..while – The condition is checked after each iteration. |
| 213 | + for (;;) – The condition is checked before each iteration, additional settings available. |
| 214 | +
|
| 215 | +
|
| 216 | + To make an “infinite” loop, usually the while(true) construct is used. Such a loop, just like any other, can be stopped with the break directive. |
| 217 | +
|
| 218 | + If we don’t want to do anything in the current iteration and would like to forward to the next one, we can use the continue directive. |
| 219 | +
|
| 220 | + break/continue support labels before the loop. A label is the only way for break/continue to escape a nested loop to go to an outer one. |
| 221 | +*/ |
0 commit comments