¿Hay alguna razón para usar la palabra clave "var" en ES6?

261

La guía de Babel para ES6 dice:

letEs lo nuevo var.

Aparentemente, la única diferencia es que varse limita a la función actual , mientras que letse limita al bloque actual . Hay algunos buenos ejemplos en esta respuesta .

No veo ninguna razón para usar varen el código ES6. Incluso si desea abarcar una variable dada a toda la función, puede hacerlo letcolocando la declaración en la parte superior del bloque de funciones, que es lo que debería hacer de vartodos modos para indicar el alcance real. Y si quieres ver algo más fino en un forbloque o algo, entonces puedes hacerlo también.

Entonces, mi instinto es dejar de usar por varcompleto al escribir el código ES6.

Mi pregunta es, ¿estoy equivocado sobre esto? ¿Hay algún caso legítimo donde varsería preferible let?

callum
fuente
3
Todavía no lo he intentado (ya que todavía no estoy escribiendo el código ES6), pero parece que usar varcomo un indicador consciente de que esta variable está destinada a toda la función podría ser una convención útil de "autodocumentación" .
jfriend00
10
Si coloca una letdeclaración justo en la parte superior de una función, creo que es igual de obvio que tenía la intención de abarcarla a toda la función. No creo que usarlo lo varhaga más claro que simplemente ubicarlo en la parte superior.
callum
11
Honestamente, creo que la única razón que varaún existe es la compatibilidad con versiones anteriores. Si no fuera por eso, se habrían eliminado por varcompleto, o nunca se habrían presentado leten primer lugar, en cambio, cambiarían la semántica vara lo que podría decirse que debería haber sido todo el tiempo.
Jörg W Mittag
2
@RayToal Estoy de acuerdo con el 97% de lo que dice Kyle Simpson, pero sus razones para seguir usando me varparecen débiles, y no lo suficiente como para garantizar tener un tercer tipo de variable que salta a la vista. Puede abarcar leta una función completa simplemente colocándola en la parte superior de la función, que tiene una intención mucho más clara que escribir varen un bloque (para que se levante de ese bloque para que luego pueda usarlo fuera del bloque - extraño). Advierte que si usted abarca leta una función, entonces "es solo la posición la que señala la diferencia, en lugar de la sintaxis", pero creo que eso es algo bueno.
callum
2
@RayToal Yo también leí ese artículo (justo antes de leer esta discusión) y estaba realmente decepcionado por su débil argumento var. Los ejemplos que presenta para mantenerlos varparecen artificiales, y se basan en graves errores de codificación. ¡Es mucho mejor encontrarse con un error y verse obligado a corregir dichos errores que usar funciones de lenguaje que le permitan salirse con la suya! ¿Qué sigue, aconseje envolver todo en un intento / captura para evitar accidentes? El resto de ese enlace es bueno, pero no estoy de acuerdo con esa parte en particular.
Mörre

Respuestas:

217

Doug Crockford discute leten este momento en su charla, " Las mejores partes ".

El punto es que letevita una fuente de malentendidos, especialmente. para programadores con expectativas establecidas por lenguajes con alcance de bloque. A vartiene alcance de función (declara una variable que es visible en toda la función) aunque parezca que tiene alcance de bloque .

var Es posible que aún sea útil en un caso extremo como el código generado por máquina, pero me estoy estirando mucho allí.

( consttambién es nuevo y tiene un alcance de bloque. Después de let x = {'hi': 'SE'}que pueda reasignar a x, mientras que después de const y = xque no pueda reasignar a y. Eso a menudo es preferible ya que evita que algo cambie accidentalmente debajo de usted. Pero para ser claros, aún puede modificar el objeto a y.hi = 'SO'menos que congelarlo.)

Siendo realistas, su impresión es correcta para ES6: adoptar lety const. Deja de usar var.

(En otra presentación de "The Better Parts" , Doug dice por qué ===se agregó en lugar de solucionar los problemas de== . ==Produce algunos resultados "sorprendentes", así que simplemente adopte ===).


Un ejemplo revelador

Mozilla Developer Network ofrece un ejemplo en el varque no funciona según lo previsto. Su ejemplo es realista y establece onclickcontroladores en una página web. Aquí hay un caso de prueba más pequeño:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

varnos falla porque todas las iteraciones de bucle comparten la misma ivariable con ámbito de función , que tiene el valor una vez que 5finaliza el bucle.

Jerry101
fuente
66
Da la misma respuesta sobre la adopción de === en lugar de ==. El último está roto, pero el comité de estándares de ES no quiso cambiarlo, por lo que agregaron === No estoy muy seguro de lo que eso significa. ==No está roto en absoluto. Simplemente se puede definir como equality comparison using coersionEcha un vistazo a github.com/getify/You-Dont-Know-JS/blob/master/…
AmmarCSE
13
@AmmarCSE es un maravilloso documento de 39 páginas sobre coacciones implícitas. ¿Quién puede tener todo eso en mente mientras programa? Doug quiso decir "roto" como se resume en stackoverflow.com/a/359509/1682419 , en resumen, fácil de obtener cuando los tipos de valor varían más de lo que suponíamos. ¿Puedes predecir todo esto? [ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101
2
correcto, la mayoría de esos ejemplos involucran un operando de matriz. Es fácil entender el resultado cuando observa toString y cómo se implementa para los Objetos . Sin embargo, si eso es lo que significa roto, entonces veo completamente de dónde viene eso. :-)
AmmarCSE
3
¿Por qué no usar const siempre que no sea mutable? Quiero decir, la verdadera elección no es entre lety varsino entre let, varyconst
shabunc
44
varfunciona según lo diseñado, pero no cuántas personas esperan. Es un error de usabilidad, no un error de implementación.
Jerry101
12

Si ha estado escribiendo el código correcto, probablemente podrá convertir todas las vardeclaraciones en letdeclaraciones sin ningún cambio semántico.

letes preferible porque reduce el alcance en el que un identificador es visible. Nos permite declarar variables de forma segura en el sitio de primer uso.

constes preferible let. A menos que necesite mutar una referencia, use una constdeclaración. Esto tiene todos los beneficios de letreducir la presencia de variables unitarias y hacer que el código sea más fácil de razonar. Si no está seguro de si necesitará mutar una referencia, declare consthasta que tenga que hacerlo explícitamente.

Aluan Haddad
fuente
5

No creo necesariamente que estés equivocado, pero hay advertencias para usar var. Esencialmente, letdebería ayudar a los desarrolladores a sortear la estupidez de JavaScript, particularmente con los conflictos de nombres. var, al parecer, tiene un alcance mayor ya que quiere ir al alcance de la función de cierre. Habrá momentos en los que necesite var, como cuando necesite que una variable temporal esté disponible dentro del alcance de un bloque dentro de una función; de lo contrario, preferir leta var ayudará a los desarrolladores a resolver conflictos de nombres. En una nota más ligera, ya es hora de que se presente ES6 let.

curioso
fuente
3
Una temperatura varen un bloque está disponible dentro de toda la función, no en ámbito de bloque. Es una característica engañosa.
Jerry101
1

Tiendo a estar de acuerdo en que solo "let" debe usarse en es6. AFIK, volver a declarar un "let" genera un error (que es bueno), mientras que con "var", simplemente anula el valor (aunque el "modo estricto" en es5 también se encarga de eso).

yar1
fuente
-4

letsignifica "dejar variable igual". Es una declaración, en otras palabras, una inicialización y asignación.

Existe en contraste con lo constque, por supuesto, significa "constante", que es lo contrario de variable.

Algunos otros lenguajes usan un prefijo para el objeto real en lugar del objeto cuando lo declaran (por ejemplo, defes una abreviatura de "definir función" - falta por completo el punto de lo que se está "def".

Let agrega esta inconsistencia semántica a Javascript.

Lógicamente, también puede permitir que una constante sea igual a algo, ya que el trabajo de la palabra clave "let" es asignar memoria.

El problema surge porque la varpalabra clave que se introdujo antes constera compatible, por lo que la compatibilidad con versiones anteriores dicta que varno necesariamente significa una variable. (También podría usarse para asignar un valor constante).

Por lo tanto, la introducción de leten la posición incorrecta. Para asegurarse de que recordamos que léxicamente, esto está mal, también decidieron cambiar el alcance léxico de letvs var, por lo que la inconsistencia es lo más importante en nuestras mentes al depurar.

En otras palabras, letexiste porque las personas (es decir, los mantenedores del lenguaje) pensaban que Javascript era demasiado consistente, habiendo dominado todos sus modismos e idiosincrasias, desean más.

Nota al margen, varno funciona en bloques de "flecha" si desea tratar dichos bloques como cierres (porque varse introdujo antes de tratar los bloques como cierres), pero lo lethace.

fijiaaron
fuente
66
-1: pedante, inútil y principalmente basado en la opinión.
Joel Mueller
Fijiaaron solo está bromeando con nosotros aquí.
Jerry101
Simpatizo con su disgusto por la forma léxica letporque está en desacuerdo con el tono de otras palabras clave en la misma categoría en JavaScript. Aún así, esto no responde a la pregunta, y no está particularmente bien planteado. Votado a favor
Aluan Haddad
3
letNo solo los desarrolladores desean más complejidad. En realidad, es intuitivamente más comprensible, porque cuando realiza un bucle y cierra sobre vars, el cierre mantiene el último valor de la var, pero cuando hace lo mismo sobre let, cada cierre en el bucle tiene su propio valor para let, un el ejemplo de @ Jerry101 arriba
TKoL