aboutsummaryrefslogtreecommitdiff
path: root/files/es/web/javascript/guide/loops_and_iteration/index.html
blob: d74307f35e3e5e31f29e3c43c3bb987ab76a71ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
---
title: Bucles e iteración
slug: Web/JavaScript/Guide/Loops_and_iteration
tags:
  - Bucle
  - Guia(2)
  - Guía
  - Iteración
  - JavaScript
  - Sintaxis
translation_of: Web/JavaScript/Guide/Loops_and_iteration
original_slug: Web/JavaScript/Guide/Bucles_e_iteración
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}</div>

<p class="summary">Los bucles ofrecen una forma rápida y sencilla de hacer algo repetidamente. Este capítulo de la {{JSxRef("../Guide", "Guía de JavaScript")}} presenta las diferentes declaraciones de iteración disponibles para JavaScript.</p>

<p>Puedes pensar en un bucle como una versión computarizada del juego en la que le dices a alguien que dé <em>X</em> pasos en una dirección y luego <em>Y</em> pasos en otra. Por ejemplo, la idea "Ve cinco pasos hacia el este" se podría expresar de esta manera como un bucle:</p>

<pre class="brush: js notranslate">for (let step = 0; step &lt; 5; step++) {
  // Se ejecuta 5 veces, con valores del paso 0 al 4.
  console.log('Camina un paso hacia el este');
}
</pre>

<p>Hay muchos diferentes tipos de bucles, pero esencialmente, todos hacen lo mismo: repiten una acción varias veces. (¡Ten en cuenta que es posible que ese número sea cero!).</p>

<p>Los diversos mecanismos de bucle ofrecen diferentes formas de determinar los puntos de inicio y terminación del bucle. Hay varias situaciones que son fácilmente atendidas por un tipo de bucle que por otros.</p>

<p>Las declaraciones para bucles proporcionadas en JavaScript son:</p>

<ul>
 <li>{{anch("Declaracion_for", "Declaración for")}}</li>
 <li>{{anch("Declaracion_do...while", "Declaración do...while")}}</li>
 <li>{{anch("Declaracion_while", "Declaración while")}}</li>
 <li>{{anch("Declaracion_labeled", "Declaración labeled")}}</li>
 <li>{{anch("Declaracion_break", "Declaración break")}}</li>
 <li>{{anch("Declaracion_continue", "Declaración continue")}}</li>
 <li>{{anch("Declaracion_for...in", "Declaración for...in")}}</li>
 <li>{{anch("Declaracion_for...of", "Declaración for...of")}}</li>
</ul>

<h2 id="Declaración_for">Declaración <code>for</code></h2>

<p>Un ciclo {{JSxRef("Sentencias/for", "for")}} se repite hasta que una condición especificada se evalúe como <code>false</code>. El bucle <code>for</code> de JavaScript es similar al bucle <code>for</code> de Java y C.</p>

<p>Una declaración <code>for</code> tiene el siguiente aspecto:</p>

<pre class="syntaxbox notranslate">for ([expresiónInicial]; [expresiónCondicional]; [expresiónDeActualización])
  instrucción
</pre>

<p>Cuando se ejecuta un bucle <code>for</code>, ocurre lo siguiente:</p>

<ol>
 <li>Se ejecuta la expresión de iniciación <code>expresiónInicial</code>, si existe. Esta expresión normalmente inicia uno o más contadores de bucle, pero la sintaxis permite una expresión de cualquier grado de complejidad. Esta expresión también puede declarar variables.</li>
 <li>Se evalúa la expresión <code>expresiónCondicional</code>. Si el valor de <code>expresiónCondicional</code> es verdadero, se ejecutan las instrucciones del bucle. Si el valor de <code>condición</code> es falso, el bucle <code>for</code> termina. (Si la expresión <code>condición</code> se omite por completo, se supone que la condición es verdadera).</li>
 <li>Se ejecuta la <code>instrucción</code>. Para ejecutar varias instrucciones, usa una declaración de bloque (<code>{ ... }</code>) para agrupar esas declaraciones.</li>
 <li>Si está presente, se ejecuta la expresión de actualización <code>expresiónDeActualización</code>.</li>
 <li>El control regresa al paso 2.</li>
</ol>

<h3 id="Ejemplo"><strong>Ejemplo</strong></h3>

<p>En el siguiente ejemplo, la función contiene una instrucción <code>for</code> que cuenta el número de opciones seleccionadas en una lista de desplazamiento (el elemento {{HTMLElement("select")}} de HTML representa un control que proporciona un menú de opciones que permite múltiples selecciones). La instrucción <code>for</code> declara la variable <code>i</code> y la inicia a <code>0</code>. Comprueba que <code>i</code> es menor que el número de opciones en el elemento <code>&lt;select&gt;</code>, realiza la siguiente instrucción <code>if</code> e incrementa <code>i</code> después de cada pasada por el bucle.</p>

<pre class="brush: html notranslate">&lt;form name="selectForm"&gt;
  &lt;p&gt;
    &lt;label for="musicTypes"&gt;Elija algunos tipos de música, luego haga clic en el botón de abajo:&lt;/label&gt;
    &lt;select id="musicTypes" name="musicTypes" multiple="multiple"&gt;
      &lt;option selected="selected"&gt;R&amp;B&lt;/option&gt;
      &lt;option&gt;Jazz&lt;/option&gt;
      &lt;option&gt;Blues&lt;/option&gt;
      &lt;option&gt;New Age&lt;/option&gt;
      &lt;option&gt;Classical&lt;/option&gt;
      &lt;option&gt;Opera&lt;/option&gt;
    &lt;/select&gt;
  &lt;/p&gt;
  &lt;p&gt;&lt;input id="btn" type="button" value="¿Cuántos están seleccionados?" /&gt;&lt;/p&gt;
&lt;/form&gt;

&lt;script&gt;
function howMany(selectObject) {
  let numberSelected = 0;
  for (let i = 0; i &lt; selectObject.options.length; i++) {
    if (selectObject.options[i].selected) {
      numberSelected++;
    }
  }
  return numberSelected;
}

let btn = document.getElementById('btn');
btn.addEventListener('click', function() {
  alert('Número de opciones seleccionadas: ' + howMany(document.selectForm.musicTypes));
});
&lt;/script&gt;

</pre>

<h2 id="Declaración_do...while">Declaración <code>do...while</code></h2>

<p>La instrucción {{JSxRef("Sentencias/do...while", "do...while")}} se repite hasta que una condición especificada se evalúe como falsa.</p>

<p>Una declaración <code>do...while</code> tiene el siguiente aspecto:</p>

<pre class="syntaxbox notranslate">do
  <em>expresión</em>
while (condición);
</pre>

<p><em><code>exposición</code></em> siempre se ejecuta una vez antes de que se verifique la condición. (Para ejecutar varias instrucciones, usa una declaración de bloque (<code>{ ... }</code>) para agrupar esas declaraciones).</p>

<p>Si <code>condición</code> es <code>true</code>, la declaración se ejecuta de nuevo. Al final de cada ejecución, se comprueba la condición. Cuando la condición es <code>false</code>, la ejecución se detiene y el control pasa a la declaración que sigue a <code>do...while</code>.</p>

<h3 id="Ejemplo_2"><strong>Ejemplo</strong></h3>

<p>En el siguiente ejemplo, el bucle <code>do</code> itera al menos una vez y se repite hasta que <code><em>i</em></code> ya no sea menor que <code>5</code>.</p>

<p>let i = 0; do { i += 1; console.log(i); } while (i &lt; 5);</p>

<h2 id="Declaración_while">Declaración <code>while</code></h2>

<p>Una declaración {{JSxRef("Sentencias/while", "while")}} ejecuta sus instrucciones siempre que una condición especificada se evalúe como <code>true</code>. Una instrucción <code>while</code> tiene el siguiente aspecto:</p>

<pre class="syntaxbox notranslate">while (<em>condición</em>)
  <em>expresión</em>
</pre>

<p>Si la <em><code>condición</code></em> se vuelve <code>false</code>, la <code>instrucción</code> dentro del bucle se deja de ejecutar y el control pasa a la instrucción que sigue al bucle.</p>

<p>La prueba de condición ocurre <em>antes</em> de que se ejecute la <code>expresión</code> en el bucle. Si la condición devuelve <code>true</code>, se ejecuta la <code>expresión</code> y la <em><code>condición</code></em> se prueba de nuevo. Si la condición devuelve <code>false</code>, la ejecución se detiene y el control se pasa a la instrucción que sigue a <code>while</code>.</p>

<p>Para ejecutar varias instrucciones, usa una declaración de bloque (<code>{ ... }</code>) para agrupar esas declaraciones.</p>

<h3 id="Ejemplo_1"><strong>Ejemplo 1</strong></h3>

<p>El siguiente ciclo del <code>while</code> se repite siempre que <em><code>n</code></em> sea menor que <code>3</code>:</p>

<pre class="brush: js notranslate">let n = 0;
let x = 0;
while (n &lt; 3) {
  n++;
  x += n;
}
</pre>

<p>Con cada iteración, el bucle incrementa <code>n</code> y agrega ese valor a <code>x</code>. Por lo tanto, <code>x</code> y <code>n</code> toman los siguientes valores:</p>

<ul>
 <li>Después de la primera pasada: <code>n</code> = <code>1</code> y <code>x</code> = <code>1</code></li>
 <li>Después de la segunda pasada: <code>n</code> = <code>2</code> y <code>x</code> = <code>3</code></li>
 <li>Después de la tercera pasada: <code>n</code> = <code>3</code> y <code>x</code> = <code>6</code></li>
</ul>

<p>Después de completar la tercera pasada, la condición <code>n &lt; 3</code> ya no es <code>true</code>, por lo que el bucle termina.<strong>Ejemplo 2</strong></p>

<p>Evita los bucles infinitos. Asegúrate de que la condición en un bucle eventualmente se convierta en <code>false</code>; de lo contrario, el bucle nunca terminará. Las declaraciones en el siguiente bucle <code>while</code> se ejecutan indefinidamente porque la condición nunca se vuelve <code>false</code>:</p>

<pre class="example-bad brush: js notranslate">// ¡Los bucles infinitos son malos!
while (true) {
  console.log('¡Hola, mundo!');
}</pre>

<h2 id="Declaración_labeled">Declaración <code>labeled</code></h2>

<p>Una {{JSxRef("Sentencias/label", "label")}} proporciona una instrucción con un identificador que te permite hacer referencia a ella en otra parte de tu programa. Por ejemplo, puedes usar una etiqueta para identificar un bucle y luego usar las declaraciones <code>break</code> o <code>continue</code> para indicar si un programa debe interrumpir el bucle o continuar su ejecución.La sintaxis de la instrucción etiquetada es similar a la siguiente:label : instrucción</p>

<p>El valor de <code><em>label</em></code> puede ser cualquier identificador de JavaScript que no sea una palabra reservada. La <code><em>declaración</em></code> que identifica a una etiqueta puede ser cualquier enunciado.</p>

<p><strong>Ejemplo</strong></p>

<p>En este ejemplo, la etiqueta <code>markLoop</code> identifica un bucle <code>while</code>.</p>

<p>markLoop: while (theMark === true) { doSomething(); }</p>

<p>Declaración <code>break</code></p>

<p>Usa la instrucción {{JSxRef("Sentencias/break", "break")}} para terminar un bucle, <code>switch</code> o junto con una declaración etiquetada.</p>

<ul>
 <li>Cuando usas <code>break</code> sin una etiqueta, inmediatamente termina el <code>while</code>, <code>do-while</code>, <code>for</code> o <code>switch</code> y transfiere el control a la siguiente declaración.</li>
 <li>Cuando usas <code>break</code> con una etiqueta, termina la declaración etiquetada especificada.</li>
</ul>

<p>La sintaxis de la instrucción <code>break</code> se ve así:</p>

<pre class="syntaxbox notranslate">break;
break [<em>label</em>];
</pre>

<ol>
 <li>La primera forma de la sintaxis termina el bucle envolvente más interno o el <code>switch.</code></li>
 <li>La segunda forma de la sintaxis termina la instrucción etiquetada específica.</li>
</ol>

<h3 id="Ejemplo_1_2"><strong>Ejemplo</strong> <strong>1</strong></h3>

<p>El siguiente ejemplo recorre en iteración los elementos de un arreglo hasta que encuentra el índice de un elemento cuyo valor es <code>theValue</code>:</p>

<pre class="brush: js notranslate">for (let i = 0; i &lt; a.length; i++) {
  if (a[i] === theValue) {
    break;
  }
}</pre>

<h3 id="Ejemplo_2_romper_una_etiqueta"><strong>Ejemplo 2:</strong> romper una etiqueta</h3>

<pre class="brush: js notranslate">let x = 0;
let z = 0;
labelCancelLoops: while (true) {
  console.log('Bucles externos: ' + x);
  x += 1;
  z = 1;
  while (true) {
    console.log('Bucles internos: ' + z);
    z += 1;
    if (z === 10 &amp;&amp; x === 10) {
      break labelCancelLoops;
    } else if (z === 10) {
      break;
    }
  }
}
</pre>

<h2 id="Declaración_continue">Declaración <code>continue</code></h2>

<p>La instrucción {{JSxRef("Sentencias/continue", "continue")}} se puede usar para reiniciar un <code>while</code>, <code>do-while</code>, <code>for</code>, o declaración <code>label</code>.</p>

<ul>
 <li>Cuando utilizas <code>continue</code> sin una etiqueta, finaliza la iteración actual del <code>while</code>, <code>do-while</code> o <code>for</code> y continúa la ejecución del bucle con la siguiente iteración. A diferencia de la instrucción <code>break</code>, <code>continue</code> no termina la ejecución del bucle por completo. En un bucle <code>while</code>, vuelve a la condición. En un bucle <code>for</code>, salta a la <code>expresión-incremento</code>.</li>
 <li>Cuando usas <code>continue</code> con una etiqueta, se aplica a la declaración de bucle identificada con esa etiqueta.</li>
</ul>

<p>La sintaxis de la instrucción <code>continue</code> se parece a la siguiente:</p>

<pre class="syntaxbox notranslate">continue [<em>label</em>];
</pre>

<h3 id="Ejemplo_1_3"><strong>Ejemplo 1</strong></h3>

<p>El siguiente ejemplo muestra un bucle <code>while</code> con una instrucción <code>continue</code> que se ejecuta cuando el valor de <code>i</code> es <code>3</code>. Por lo tanto, <code>n</code> toma los valores <code>1</code>, <code>3</code>, <code>7</code> y <code>12</code>.</p>

<pre class="brush: js notranslate">let i = 0;
let n = 0;
while (i &lt; 5) {
  i++;
  if (i === 3) {
    continue;
  }
  n += i;
  console.log(n);
}
//1,3,7,12


let i = 0;
let n = 0;
while (i &lt; 5) {
  i++;
  if (i === 3) {
     // continue;
  }
  n += i;
  console.log(n);
}
// 1,3,6,10,15
</pre>

<h3 id="Ejemplo_2_2"><strong>Ejemplo 2</strong></h3>

<p>Una declaración etiquetada <em><code>checkiandj</code></em> contiene una declaración etiquetada <em><code>checkj</code></em>. Si se encuentra <code>continue</code>, el programa termina la iteración actual de <em><code>checkj</code></em> y comienza la siguiente iteración. Cada vez que se encuentra <code>continue</code>, <em><code>checkj</code></em> reitera hasta que su condición devuelve <code>false</code>. Cuando se devuelve <code>false</code>, el resto de la instrucción <em><code>checkiandj</code></em> se completa y <em><code>checkiandj</code></em> reitera hasta que su condición devuelve <code>false</code>. Cuando se devuelve <code>false</code>, el programa continúa en la declaración que sigue a <em><code>checkiandj</code></em>.</p>

<p>Si <code>continue</code> tuviera una etiqueta de <em><code>checkiandj</code></em>, el programa continuaría en la parte superior de la declaración <em><code>checkiandj</code></em>.</p>

<p>let i = 0; let j = 10; checkiandj: while (i &lt; 4) { console.log(i); i += 1; checkj: while (j &gt; 4) { console.log(j); j -= 1; if ((j % 2) === 0) { continue checkj; } console.log(j + 'es impar.'); } console.log('i = ' + i); console.log('j = ' + j); }</p>

<h2 id="Declaración_for...in">Declaración <code>for...in</code></h2>

<p>La instrucción {{JSxRef("Sentencias/for...in", "for...in")}} itera una variable especificada sobre todas las propiedades enumerables de un objeto. Para cada propiedad distinta, JavaScript ejecuta las instrucciones especificadas. Una declaración <code>for...in</code> tiene el siguiente aspecto:</p>

<pre class="syntaxbox notranslate">for (variable in objeto)
  instrucción
</pre>

<h3 id="Ejemplo_3"><strong>Ejemplo</strong></h3>

<p>La siguiente función toma como argumento un objeto y el nombre del objeto. Luego itera sobre todas las propiedades del objeto y devuelve una cadena que enumera los nombres de las propiedades y sus valores.</p>

<pre class="brush: js notranslate">function dump_props(obj, obj_name) {
  let result = '';
  for (let i in obj) {
    result += obj_name + '.' + i + ' = ' + obj[i] + '&lt;br&gt;';
  }
  result += '&lt;hr&gt;';
  return result;
}
</pre>

<p>Para un objeto <code>car</code> con propiedades <code>make</code> y <code>model</code>, <code>result</code> sería:</p>

<pre class="brush: js notranslate">car.make = Ford
car.model = Mustang
</pre>

<h3 id="Arrays"><strong>Arrays</strong></h3>

<p>Aunque puede ser tentador usar esto como una forma de iterar sobre los elementos {{JSxRef("Array")}}, la instrucción <code>for...in</code> devolverá el nombre de sus propiedades definidas por el usuario además de los índices numéricos.</p>

<p>Por lo tanto, es mejor usar un bucle {{JSxRef("Sentencias/for", "for")}} tradicional con un índice numérico cuando se itera sobre arreglos, porque la instrucción <code>for...in</code> itera sobre las propiedades definidas por el usuario además de los elementos del arreglo, si modificas el objeto <code>Array</code> (tal como agregar propiedades o métodos personalizados).</p>

<h2 id="Declaración_for...of">Declaración <code>for...of</code></h2>

<p>La declaración {{JSxRef("Sentencias/for...of", "for...of")}} crea un bucle que se repite sobre {{JSxRef("../Guide/iterable", "objetos iterables")}} (incluidos {{JSxRef("Array")}}, {{JSxRef("Map")}}, {{JSxRef("Set")}}, objetos {{JSxRef("Funciones/arguments", "arguments")}} y así sucesivamente), invocando un gancho de iteración personalizado con declaraciones que se ejecutarán para el valor de cada distinta propiedad.</p>

<pre class="syntaxbox notranslate">para (<em>variable</em> of <em>objeto</em>)
  <em>expresión</em>
</pre>

<p>El siguiente ejemplo muestra la diferencia entre un bucle for<code>...in</code> y un bucle {{JSxRef("Sentencias/for...in", "for...in")}}. Mientras que <code>for...in</code> itera sobre los nombres de propiedad, <code>for...of</code> itera sobre los valores de propiedad:</p>

<pre class="brush:js notranslate">const arr = [3, 5, 7];
arr.foo = 'hola';

for (let i in arr) {
   console.log(i); // logs "0", "1", "2", "foo"
}

for (let i of arr) {
   console.log(i); // logs 3, 5, 7
}
</pre>

<p>{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}</p>