¿Cuánto debería usar 'let' vs 'const' en ES6?

214

He estado escribiendo mucho código ES6 para io.js recientemente. No hay mucho código en la naturaleza para aprender, así que siento que estoy definiendo mis propias convenciones a medida que avanzo.

Mi pregunta es acerca de cuándo utilizar constvs let.

He estado aplicando esta regla: si es posible, úsala const. Úselo solo letsi sabe que su valor debe cambiar. (Siempre puede regresar y cambiar a consta a letsi luego resulta que necesita cambiar su valor).

La razón principal de esta regla es que es fácil de aplicar de manera consistente. No hay zonas grises.

La cuestión es que, cuando aplico esta regla, en la práctica lo son el 95% de mis declaraciones const. Y esto me parece raro. Solo lo uso letpara cosas como ien un forbucle, u ocasionalmente para cosas como los totales acumulados de Fibonacci (que no aparece mucho en la vida real). Me sorprendió esto: resulta que el 95% de las 'variables' en mi código ES5 hasta la fecha eran para valores que no varían. Pero ver consttodo mi código se siente mal de alguna manera.

Entonces mi pregunta es: ¿está bien usar consttanto? ¿Realmente debería estar haciendo cosas como const foo = function () {...};?

¿O debería reservar constpara ese tipo de situaciones en las que está codificando un literal en la parte superior de un módulo, como el que hace en mayúsculas const MARGIN_WIDTH = 410;?

callum
fuente
77
Sospecho que esta pregunta se basa principalmente en la opinión y, por lo tanto, es probable que se cierre, pero mis 2 centavos: está bien usar constesto.
jhominal
15
function foo() {...}es mejor que<anything> foo = function() {...}
OrangeDog
12
@OrangeDog Me gustaría ver su explicación para eso, ya que concluí exactamente lo contrario. Hay una advertencia que function foo() {...}puede causar una confusión menor al depurar, debido a la elevación. Además, su existencia significa que tenemos dos construcciones que hacen lo mismo, pero una de ellas solo funciona en un contexto muy específico. (Puede usar una expresión de función en cualquier lugar donde pueda existir una expresión, pero solo puede usar una declaración de función a nivel de enunciado). Si favorece la brevedad, el problema podría ser que la sintaxis de expresión de función use la palabra completa function.
Keen
11
Las trazas de pila tienen el nombre de la función en lugar de anon. El izado es bueno y le permite definir funciones en un orden natural, sin tener que preocuparse por la indefinición.
OrangeDog
1
Esos son buenos puntos a tener en cuenta, pero aún no estoy convencido. Los depuradores modernos hacen un buen trabajo al elegir el nombre para mostrar correcto para su función en función del símbolo al que lo asigna (si lo hay, si no hay ninguno, puede usar una expresión de función con nombre). La declaración natural del orden de funciones es altamente subjetiva. Puede ser razonable pensar que el orden natural es comenzar definiendo las piezas básicas, y luego definir las piezas que las usan.
Keen

Respuestas:

183

Mi respuesta aquí no es específica de JavaScript.

Como regla general en cualquier idioma que me permita hacerlo de una manera semi fácil, diría que siempre use const / final / readonly / como se llame en su idioma siempre que sea posible. La razón es simple, es mucho más fácil razonar sobre el código cuando es obvio qué puede cambiar y qué no. Y además de esto, en muchos idiomas puede obtener soporte de herramientas que le indica que está haciendo algo mal cuando asigna de forma accidental a una variable que ha declarado como constante.

Volver atrás y cambiar una constante a una let es muy simple. Y seguir const por defecto te hace pensar dos veces antes de hacerlo. Y esto es en muchos casos algo bueno.

¿Cuántos errores has visto que implican que las variables cambien inesperadamente? Supongo que mucho. Sé que la mayoría de los errores que veo implican cambios de estado inesperados. No eliminarás todos estos errores usando liberalmente const, ¡pero eliminarás muchos de ellos!

Además, muchos lenguajes funcionales tienen variables inmutables donde todas las variables son constantes por defecto. Mira Erlang por ejemplo, o F #. La codificación sin asignación funciona perfectamente en estos lenguajes y es una de las muchas razones por las cuales las personas aman la programación funcional. Hay mucho que aprender de estos idiomas sobre la gestión del estado para convertirse en un mejor programador.

¡Y todo comienza con ser extremadamente liberal con const! ;) Son solo dos caracteres más para escribir en comparación con let, ¡así que adelante y consttodas las cosas!

wasatz
fuente
45
constson dos personajes más que let...
OrangeDog
72
Pero 5 caracteres menos que inmutables.
Cerad
77
Esto se parece mucho al uso valen Scala (que declara una variable como inmutable) y solo al uso var(el equivalente mutable) cuando no podemos usarlo val. En otras palabras, declaramos las variables como inmutables por defecto y solo introducimos la mutabilidad cuando la necesitamos absolutamente (lo cual puede ser simplemente porque el enfoque mutable es más limpio).
Kat
77
Estoy de acuerdo con esta respuesta, pero tenga en cuenta que las cosas no son tan obvias cuando se trabaja con objetos simples o matrices, ya que sus propiedades pueden cambiar incluso si se definieron con 'const'. Había pensado que 'const' funcionaba como object.freeze, pero ese no es el caso.
backdesk
2
@ Cerad ¿Querías decir "4 caracteres menos" o me estoy perdiendo alguna broma aquí?
Mathias Bynens
57

Tenga cuidado, porque las constclaves de objeto son mutables.

Desde aquí: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

las claves de objeto no están protegidas

considera este ejemplo:

const colors = {red: "#f00"}; 
console.log(colors); // { "red": "#f00" }

colors.red = "#00f";
colors.green = "#0f0";
console.log(colors); // { "red": "#00f", "green": "#0f0" }

Lo mismo para las matrices:

const numbers = [1, 2, 3];
console.log(numbers); // [ 1, 2, 3 ]

numbers.push(4);
console.log(numbers); // [ 1, 2, 3, 4 ]

No me he decidido totalmente a mí mismo, pero estoy considerando usarlo constpara todos los objetos que no sean matrices / no y usarlos letpara objetos / matrices.

lax4mike
fuente
34
Verdadero, pero esperado IMO: lo que es constante es la referencia de objeto asignada a su const. colors = numbersno funcionará, como se esperaba. Si desea proteger las propiedades de sus objetos, puede usar Object.freeze() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Josef Engelfrost
16
Engañoso. Es inmutable. Pero las propiedades reales del objeto no lo son.
Gaston Sanchez
1
+1 Sí, la referencia está protegida, pero en términos de la pregunta , es bastante tonto usarla en casos como const moment = require('moment'), a menos que seas el tipo de persona que está preocupada de que alguien intente hacerlo moment = dead.fish(() => pizza)más tarde.
MaxWell
55
Quizás más realista de qué preocuparse moment = Date.now(). Pero, en cualquier caso, si el código supone una invariante, no veo nada de malo en aplicarlo siempre que sea posible.
James M.
3
Sin embargo, nadie dijo que no fueran inmutables. Es un malentendido común que el objetivo de const es hacerlo inmutable, cuando realmente es garantizar que el nombre nunca haga referencia a un objeto diferente al que se inicializó.
Monokrome
25

No te preocupes por eso. constes una adición increíble a JavaScript, y recomendaría que lo use en todos los lugares que tenga sentido. Hace un código más robusto.

Cuando se trata de objetos, constprotegerá su variable de la reasignación, pero si necesita objetos inmutables, necesitará el Object.freezemétodo, consulte a continuación.

const immutableOject = Object.freeze({immutableProperty: 'foo'});

constprotegerá solo de la reasignación, y el freezemétodo protegerá todas las propiedades inmediatas. Si necesita que todas las propiedades anidadas también sean inmutables, deberá recurrirlas recursivamente freeze.

clean_coding
fuente
14
Tenga en cuenta que Object.freezees poco profundo.
Mathias Bynens
@MathiasBynens Me encontré con este comentario y tengo curiosidad por saber a qué te referías exactamente. ¿Podrías por favor elaborar?
Cole Roberts
@ColeRoberts El concepto de inmutabilidad superficial es cuando la referencia del objeto en sí es inmutable, pero las propiedades aún se pueden cambiar. La palabra clave const solo permite una inmutabilidad superficial, por lo tanto, debe usar Object.freeze si todas las propiedades también deben ser inmutables.
clean_coding
3
@ColeRoberts Significa que los valores de objeto dentro de un objeto congelado (es decir, objetos anidados) aún pueden mutarse. Consulte mathiasbynens.be/notes/es6-const#immutable-values para obtener más información.
Mathias Bynens
19

En mi ES6 constno se trata de la publicación de inmutabilidad , explico lo que constsignifica exactamente de acuerdo con las especificaciones.

Basado en esos hechos objetivos, aquí está mi preferencia personal:

[…] Tiene sentido usar lety constcomo sigue en su código ES6:

  • usar constpor defecto
  • solo se usa letsi se necesita volver a vincular (es decir, cualquier forma de reasignación)
  • ( varno debe usarse en ES6)

Por subjetivo que sea, es un hecho que esto coincide más estrechamente con la intención de la especificación.

Las personas que usan letpor defecto generalmente tratan las constvariables como constantes (¡lo cual no es necesariamente, por diseño!). A cada uno lo suyo, pero prefiero usar las cosas para su propósito previsto, y no para un significado inventado que las personas le asignan en base a un malentendido.

Usar constsolo para constantes es como usar el <aside>elemento HTML solo para el contenido de la barra lateral.

Mathias Bynens
fuente
2
¿Por qué nombrarías algo constsi no es constante?
nu everest
3
@nueverest Porque eso no constes para lo que sirve. ¿Leíste lo anterior?
Mathias Bynens
2
@MathiasBynens Creo que el problema (¿solo?) constEs que se llama const. Es un nombre tonto (en javascript) que confunde a muchos (¿todos?) Desarrolladores al principio. OMI sería mejor si consthubiera sido llamado let(especialmente porque letes más corto pero constes mucho más común) y se letllama otra cosa.
MrN00b
@MathiasBynens Lo entiendo, pero ¿por qué llamarlo así? Está creando una gran cantidad de confusión como lo demuestra esta página.
jtr13
4

Mi enfoque personal, pensado para ayudar a la legibilidad y comprensión del código:


letes solo para variables de corta duración, definidas en una sola línea y no modificadas después. Generalmente aquellas variables que están ahí solo para disminuir la cantidad de tipeo. Por ejemplo:

for (let key in something) {
  /* we could use `something[key]` for this entire block,
     but it would be too much letters and not good for the
     fingers or the eyes, so we use a radically temporary variable
  */
  let value = something[key]
  ...
}

constpara todos los nombres que se sabe que son constantes en todo el módulo. No incluye valores locales constantes. En valueel ejemplo anterior, por ejemplo, es constante en su alcance y podría declararse con const, pero dado que hay muchas iteraciones y para cada una hay un valor con el mismo nombre , "valor", que podría engañar al lector para valueque siempre piense lo mismo. Los módulos y funciones son el mejor ejemplo de constvariables:

const PouchDB = require('pouchdb')
const instantiateDB = function () {}
const codes = {
  23: 'atc',
  43: 'qwx',
  77: 'oxi'
}

varpara todo lo que puede o no ser variable. Los nombres que pueden confundir a las personas que leen el código, incluso si son constantes localmente y no son adecuados let(es decir, no se completan en una declaración directa simple), se solicitan para ser declarados con var. Por ejemplo:

var output = '\n'
lines.forEach(line => {
  output += '  '
  output += line.trim()
  output += '\n'
})
output += '\n---'

for (let parent in parents) {
  var definitions = {}
  definitions.name = getName(parent)
  definitions.config = {}
  definitions.parent = parent
}

Comentarios adicionales y posibles actualizaciones futuras aquí .

fiatjaf
fuente
10
ese segundo fragmento de código parece una pistola.
Juliano
1

JavaScript es un poco especial en el sentido de que las variables pueden ser funciones y demás, pero tenga en cuenta en C #, Java u otro lenguaje de estilo C similar:

const public void DoSomething()

El constes impar, y eso se debe a declaraciones de métodos en estos idiomas no pueden cambiar, una vez que se compilan en otra cosa, eso es lo que hacen, no importa lo que (ignorando algunos hacks horribles que puedan existir).

¿Por qué debería ser JavaScript diferente? Por lo tanto, no se compila, pero eso no significa que debamos descartar la seguridad que los compiladores pueden proporcionar. El uso de la constpalabra clave nos brinda más seguridad, lo que seguramente conducirá a aplicaciones más robustas.

Joe
fuente