aboutsummaryrefslogtreecommitdiff
path: root/files/es/web/javascript/referencia/sentencias/let/index.html
blob: 8c450b37d4c8851cd0441809d6f964913186531d (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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
---
title: let
slug: Web/JavaScript/Referencia/Sentencias/let
tags:
  - Característica del lenguaje
  - Declaración de variable
  - ECMAScript 2015
  - JavaScript
  - Variables
  - let
  - sentencias
translation_of: Web/JavaScript/Reference/Statements/let
---
<div>{{jsSidebar("Statements")}}</div>

<p>La instrucción <strong><code>let</code></strong> declara una variable de alcance local con ámbito de bloque<font><font>(</font></font><a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/block">block </a>scope<font><font>)</font></font>, la cual, opcionalmente, puede ser inicializada con algún valor.</p>

<div class="warning">
<p class="p1">La palabra reservada <strong><code><span class="s1">let </span></code></strong>en Mozilla Firefox 44 y anteriores, está solo disponible para bloques de código en HTML que esten envueltos en una etiqueta <code><span class="s1">&lt;script type="application/javascript;version=1.7"&gt;</span></code> (o de una version mayor). Las etiquetas <a href="https://developer.mozilla.org/en-US/docs/XUL">XUL</a> tienen acceso a esas características sin necesidad de dicho bloque.  Es necesario tomar en cuenta que esta es una característica <s>no estándar</s> <u>que ya se ha hecho actualmente estándar</u>, <s>esto</s> <u>pero</u> puede crear conflictos con otros navegadores<u>, ya que fue una característica no estándar.</u></p>
</div>

<h2 id="Sintaxis">Sintaxis</h2>

<pre class="syntaxbox notranslate">let var1 [= valor1] [, var2 [= valor2]] [, ..., varN [= valorN]];</pre>

<h3 id="Parámetros">Parámetros</h3>

<dl>
 <dt><code>var1</code>, <code>var2</code>, …, <code>varN</code></dt>
 <dd>Los nombres de la variable o las variables a declarar. Cada una de ellas debe ser un identificador legal de JavaScript</dd>
 <dt><code>value1</code>, <code>value2</code>, …, <code>valueN</code></dt>
 <dd>Por cada una de las variables declaradas puedes, opcionalmente, especificar su valor inicial como una expresión legal JavaScript.</dd>
</dl>

<h2 id="Descripción">Descripción</h2>

<p><strong><code>let</code> </strong>te permite declarar variables limitando su alcance (<em>scope</em>) al bloque, declaración, o expresión donde se está usando.a diferencia de la palabra clave <code>var</code> la cual define una variable global o local en una función sin importar el ámbito del bloque. La otra diferencia entre <code>var</code> y <code>let</code> <span class="VIiyi" lang="es"><span class="ChMk0b JLqJ4b"><span>es que este último se inicializa a un valor sólo cuando un analizador lo evalúa (ver abajo).</span></span></span></p>

<p>Al igual que <code>const</code>, <code>let </code>no crea propiedades del objeto se declara globalmente (en el alcance más alto).</p>

<h3 id="Alcance_scope_a_nivel_de_bloque_con_let">Alcance (<em>scope</em>) a nivel de bloque con <code>let</code></h3>

<p>Usar la palabra reservada <code>let</code> para definir variables dentro de un bloque.</p>

<pre class="brush:js notranslate">if (x &gt; y) {
  let gamma = 12.7 + y;
  i = gamma * x;
}
</pre>

<p>Es posible usar definiciones <code>let</code> para asociar código en extensiones con un pseudo-espacio-de-nombre (pseudo-namespace). (Ver <a href="/en-US/docs/Security_best_practices_in_extensions" title="en-US/docs/Security_best_practices_in_extensions">Mejores prácticas de seguridad en extensiones</a>.)</p>

<pre class="brush:js notranslate">let Cc = Components.classes, Ci = Components.interfaces;
</pre>

<p><code>let</code> puede ser útil para escribir código más limpio cuando usamos funciones internas.</p>

<pre class="brush:js notranslate">var list = document.getElementById("list");

for (var i = 1; i &lt;= 5; i++) {
  var item = document.createElement("LI");
  item.appendChild(document.createTextNode("Item " + i));

  let j = i;
  item.onclick = function (ev) {
    console.log("Item " + j + " is clicked.");
  };
  list.appendChild(item);
}
</pre>

<p>El ejemplo anterior trabaja como se espera porque las cinco instancias de la función (anónima) interna hacen referencia a cinco diferentes instancias de la variable <code>j</code>. Nótese que esto no funcionaría como se espera si reemplazamos <code>let</code> con <code>var</code> o si removemos la variable <code>j</code> y simplemente usamos la variable <code>i</code> dentro de la función interna.</p>

<h4 id="Reglas_de_alcance">Reglas de alcance</h4>

<p>Variables declaradas por <code>let</code> tienen por alcance el bloque en el que se han definido, así mismo, como en cualquier bloque interno. De esta manera, <code>let</code> trabaja muy parecido a <code>var</code>. La más notable diferencia es que el alcance de una variable <code>var</code> es la función contenedora:</p>

<pre class="brush:js notranslate">function varTest() {
  var x = 31;
  if (true) {
    var x = 71;  // ¡misma variable!
    console.log(x);  // 71
  }
  console.log(x);  // 71
}

function letTest() {
  let x = 31;
  if (true) {
    let x = 71;  // variable diferente
    console.log(x);  // 71
  }
  console.log(x);  // 31
}
// llamamos a las funciones
varTest();
letTest();
</pre>

<p>En el nivel superior de un programa y funciones, <code>let</code> , a diferencia de <code>var</code>, <strong>no crea</strong> una propiedad en el objeto global, por ejemplo:</p>

<pre class="brush:js notranslate">var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
</pre>

<p>La salida de este código desplegaría "global" una vez.</p>

<h3 id="Zona_muerta_temporal_y_errores_con_let">Zona muerta temporal y errores con <code>let<a id="muerta" name="muerta"></a></code></h3>

<p>La <strong>redeclaración</strong> de la misma variable bajo un mismo <font><font><a href="https://www.ecma-international.org/ecma-262/6.0/#sec-lexical-environments">ámbito léxico</a> </font></font>terminaría en un error de tipo <code><a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/SyntaxError" title="SyntaxError">SyntaxError</a></code>. Esto también es <strong>extensible</strong> si usamos <code>var</code> dentro del <font><font>ámbito léxico</font></font>. Esto nos salvaguarda de redeclarar una variable accidentalmente y que no era posible  solo con <code>var.</code></p>

<pre class="brush: js notranslate">if (x) {
  let foo;
  let foo; // Terminamos con un SyntaxError.
}
if (x) {
  let foo;
  var foo; // Terminamos con un SyntaxError.
}
</pre>

<p>En ECMAScript 2015, <code>let</code> <a href="https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/var#Description">no eleva</a> la variable a la parte superior del bloque. Si se hace una referencia a la variable declarada con <code>let</code> (<code>let foo</code>) antes de su declaración, terminaríamos con un error de tipo <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/ReferenceError" title="TypeError">ReferenceError</a> </code>(al contrario de la variable declarada con <code>var</code>, que tendrá el valor <code>undefined</code>), esto porque la variables vive en una "zona muerta temporal" desde el inicio del bloque hasta que la declaración ha sido procesada.</p>

<pre class="notranslate"><code>function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError: foo </code>no está definido<code>
  var bar = 1;
  let foo = 2;
}</code></pre>

<p>Es posible encontrar errores en bloques de control <a href="/en-US/docs/JavaScript/Reference/Statements/switch" title="switch"><code>switch</code></a> debido a que solamente existe un block subyacente.</p>

<pre class="brush: js notranslate">switch (x) {
  case 0:
    let foo;
    break;

  case 1:
    let foo; // Terminamos con un error de tipo SyntaxError.
             // esto debido a la redeclaracion
    break;
}</pre>

<h3 id="Otro_ejemplo_de_zona_muerta_temporal_combinada_con_ámbito_léxico"><font><font>Otro ejemplo de zona muerta temporal combinada con <a href="https://www.ecma-international.org/ecma-262/6.0/#sec-lexical-environments">ámbito léxico</a></font></font></h3>

<p>Debido al alcance léxico, el identificador <code>num</code> dentro de la expresión (<code>num + 55</code>) se evalúa como <code>num</code> del bloque <code>if</code>, y no como la variable <code>num</code> con el valor 33 que esta por encima</p>

<p>En esa misma línea, el <code>num </code>del bloque <code>if</code> ya se ha creado en el ámbito léxico, pero aún no ha alcanzado (y <strong>terminado</strong>) su inicialización (que es parte de la propia declaración): todavía está en la zona muerta temporal.</p>

<pre class="notranslate"><code>function prueba(){
   var num = 33;
   if (true) {
      let num = (num + 55);</code>//ReferenceError: no se puede acceder a la declaración léxica `num'antes de la inicialización <code>
   }
}
prueba();</code>
</pre>

<h2 id="Ejemplos">Ejemplos</h2>

<h3 id="let_vs_var"><code>let</code> vs <code>var</code></h3>

<p>Cuando usamos <code>let</code> dentro de un bloque, podemos limitar el alcance de la variable a dicho bloque. Notemos la diferencia con <code>var</code>, cuyo alcance reside dentro de la función donde ha sido declarada la variable.</p>

<pre class="brush: js notranslate">var a = 5;
var b = 10;

if (a === 5) {
  let a = 4; // El alcance es dentro del bloque if
  var b = 1; // El alcance es global

  console.log(a);  // 4
  console.log(b);  // 1
}

console.log(a); // 5
console.log(b); // 1</pre>

<h3 id="let_en_bucles"><code>let</code> en bucles</h3>

<p>Es posible usar la palabra reservada <code>let</code> para enlazar variables con alcance local dentro del alcance de un bucle en lugar de usar una variable global (definida usando <code>var</code>) para dicho propósito.</p>

<pre class="brush: js notranslate">for (let i = 0; i&lt;10; i++) {
  console.log(i); // 0, 1, 2, 3, 4 ... 9
}

console.log(i); // ReferenceError: i is not defined
</pre>

<h2 id="Extensiones_let_no-estandar">Extensiones <code>let</code> no-estandar</h2>

<h3 id="Bloques_let">Bloques<code> let</code></h3>

<div class="warning">
<p>La <strong>sintaxis del bloque y expresion</strong> <code>let</code> es no-estandar y sera deshechado en un futuro. ¡No deben ser usados! ver <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1023609" rel="noopener" title="FIXED: Remove SpiderMonkey support for let expressions">error 1023609</a> y <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1167029" rel="noopener" title="FIXED: Remove SpiderMonkey support for let blocks">error 1167029</a> para mas detalles.</p>
</div>

<p>Un <strong>bloque <code>let</code></strong> provee una manera de asociar valores con variables dentro del alcance de un bloque sin afectar el valor de variables con nombre similar fuera del bloque.</p>

<h4 id="Sintaxis_2">Sintaxis</h4>

<pre class="syntaxbox notranslate">let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) {declaración};</pre>

<h4 id="Descripción_2">Descripción</h4>

<p>El bloque <code>let</code> provee alcance local para las variables. Funciona enlazando cero o más variables en el alcance léxico de un solo bloque de código; de otra manera, es exactamente lo mismo que una declaración de bloque. Hay que notar particularmente que el alcance de una variable declarada dentro de un bloque <code>let</code> usando var es equivalente a declarar esa variable fuera del bloque <code>let</code>; dicha variable aún tiene alcance dentro de la función. Al usar la sintaxis de bloque <code>let</code>, los paréntesis siguientes a <code>let</code> son requeridos. Una falla al incluir dichos paréntesis resultará en un error de sintaxis.</p>

<h4 id="Ejemplo">Ejemplo</h4>

<pre class="brush:js notranslate">var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

console.log(x + y); // 5
</pre>

<p>Las reglas para el bloque de código son las mismas que para cualquier otro bloque de código en JavaScript. Es posible tener sus propias variables locales usando declaraciones <code>let</code> en dicho bloque.</p>

<h4 id="Reglas_de_alcance_2">Reglas de alcance</h4>

<p>El alcance de las variables definidas usando <code>let</code> es el mismo bloque <code>let</code>, así como cualquier bloque interno contenido dentro de el bloque, a menos que esos bloques internos definan variables con el mismo nombre.</p>

<h3 id="expresiones_let">expresiones <code>let</code></h3>

<div class="warning">
<p><code>Soporte de <strong>expresiones</strong> let</code> ha sido removido en Gecko 41 ({{bug(1023609)}}).</p>
</div>

<p>Una <strong>expresion <code>let</code></strong> permite establecer variables con alcance dentro de una expresión.</p>

<h4 id="Sintaxis_3">Sintaxis</h4>

<pre class="syntaxbox notranslate">let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;</pre>

<h4 id="Ejemplo_2">Ejemplo</h4>

<p>Podemos usar <code>let</code> para establecer variables que tienen como alcance solo una expresión:</p>

<pre class="brush: js notranslate">var a = 5;
let(a = 6) console.log(a); // 6
console.log(a); // 5</pre>

<h4 id="Reglas_de_alcance_3">Reglas de alcance</h4>

<p>Dada la expresión <code>let</code> siguiente:</p>

<pre class="eval notranslate">let (<var>decls</var>) <var>expr</var>
</pre>

<p>Existe un bloque implícito creado alrededor de expr.</p>

<h2 id="Especificaciones">Especificaciones</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Especificación</th>
   <th scope="col">Estado</th>
   <th scope="col">Comentarios</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-let-and-const-declarations', 'Let and Const Declarations')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Definición initial. No especifica expresiones ni declaraciones let.</td>
  </tr>
 </tbody>
</table>

<h2 id="Compatibilidad_en_navegadores">Compatibilidad en navegadores</h2>

<h2 id="CompatibilityTable"><span style="font-size: 14px; font-weight: normal; line-height: 1.5;">{{CompatibilityTable}}</span></h2>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Característica</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>Soporte básico</td>
   <td>
    <p class="p1">{{CompatChrome(41.0)}}</p>
   </td>
   <td>{{ CompatGeckoDesktop("1.8.1") }} [1]</td>
   <td>11</td>
   <td>17</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Zona muerta temporal</td>
   <td>{{CompatUnknown}}</td>
   <td>{{ CompatGeckoDesktop("35") }} [1]</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Expresión<code> let</code> {{non-standard_inline}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoDesktop("1.8.1") }}-{{ CompatGeckoDesktop("40") }} [1]</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
  <tr>
   <td>Bloque<code> let</code> {{non-standard_inline}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoDesktop("1.8.1") }} [1]</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Característica</th>
   <th>Android</th>
   <th>Chrome para Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Soporte básico</td>
   <td>{{CompatUnknown}}</td>
   <td>
    <p class="p1">{{CompatChrome(41.0)}}</p>
   </td>
   <td>{{ CompatGeckoMobile("1.8.1") }} [1]</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Zona muerta temporal</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{ CompatGeckoMobile("35") }} [1]</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Expresión<code> let</code> {{non-standard_inline}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoMobile("1.8.1") }}-{{ CompatGeckoMobile("40") }}[1]</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
  <tr>
   <td>Bloque<code> let</code> {{non-standard_inline}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoMobile("1.8.1") }} [1]</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
 </tbody>
</table>
</div>

<h3 id="Notas_específicas_a_Firefox">Notas específicas a Firefox</h3>

<ul>
 <li>[1]: Solo disponible para bloques de codigo HTML dentro de una etiqueta <code>&lt;script&gt; type="application/javascript;version=1.7"&gt;</code> (o de una versión mayor). Es necesario tomar en cuenta que esta es una característica no estándar, esto puede crear conflictos con otros navegadores. Las etiquetas <a href="https://developer.mozilla.org/en-US/docs/XUL">XUL</a> tienen acceso a esas características sin necesidad de dicho bloque. Ver<span style="line-height: 1.5;">{{bug(932513)}}.</span></li>
 <li>Conformidad con ES2015 para <code>let</code> en SpIderMonkey es monitoreado en {{bug(950547)}} y extensiones no-standar seran eliminadas en el futuro {{bug(1023609)}}.</li>
</ul>

<h2 id="Ver_también">Ver también</h2>

<ul>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/var"><code>var</code></a></li>
 <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/const"><code>const</code></a></li>
</ul>