
JavaScript variables: var and let and const - pjlamb12
https://www.prestonlamb.com/blog/javascript-variables-var-and-let-and-const
======
dlbucci
Having used Kotlin for a while now, I find it really unfortunate that `const`
wasn't `val` for the sole reason that it's 5 characters instead of 3. `val`
would have matched nice with `let`, and my multi-variable declaration
statements could have had a nice 4-space indentation while still being all
aligned.

I know it can be confused with `var`, but no one should ever use that now that
`let` exists.

One of these days I'll write my own little language that compiles to
TypeScript or something and fix that :)

~~~
hombre_fatal
A solution I prefer is Rust's where the immutable binding is default "let x"
and you opt-in with a modifier to make it mutable "let mut x".

It just makes sense for the immutable case to be default by design instead of
just by developer habit.

"var" vs "val" always were too similar for me.

~~~
bobbylarrybobby
Swift’s var and let are also good. There is no “default” but “let” is
obviously preferred

------
jakub_g
There's one non-obvious corollary from the fact that using let/const before
declaring throws an error and var does not:

If you have let/const in your source code, but you use babel to transform it
to ES5, you may have cases where you use let/const in that error-throwing way,
but it's compiled down to var, and all is good (apart from variable being
undefined when used).

When you however upgrade your babel conf to output ES6 and not compile down to
var, you'll be having reference errors in those places, which may explode your
app. I learned in production after enabling "differential serving"
(module/nomodule).

There's an eslint plugin that can check for this stuff, but it finds false
positives in 95% of cases (matter of personal preference - it disallows "valid
but not blessed by the authors" behavior), so it's very likely you don't have
it enabled, just like us.

~~~
thewarrior
So transpiling down to ES5 doesn’t preserve semantics ?

~~~
jakub_g
For some features, having 100% spec compliant behavior in transpiled code
would mean excruciatingly slow/bloated code, or be downright impossible.
There's a reason why features are added to the language after all: to add
things that are impossible or too complex to write in old version of language.

Transpilation is "best effort" and involves some tradeoffs.

------
rofo1
Use const always, unless you must use let. That's it.

You don't need to read other articles on this subject, it's that simple.

~~~
DaiPlusPlus
`var` creates global properties when used in the global scope, which is useful
at times.

~~~
neurotrace
If you really, really need a global then you should assign it to
`window/global/globalThis` instead of relying on the weird behavior of `var`

~~~
wolco
What do you find weird about var?

~~~
DaiPlusPlus
It's weird because it has side-effects (namely, implicitly adding/setting a
named property in the current scope object, if any).

It means that a top-level script using `var` that is subsequently refactored
into a scoped function somewhere will now have different semantics and might
break if other code depended on `var` creating a new global property.

------
cryptica
I use `let` mostly and I only use `const` for special cases when changing the
variable would break the program and I want to constrain future developers
from doing that. For example, when I import some library references in Node.js
using `require`, I will use `const` or if I need to define a magic number like
`const HANDSHAKE_TIMEOUT = ...`.

I don't see the point of using const everywhere though because I don't code in
a pure functional style and I don't pretend to.

Often, it makes sense to re-assign a variable and I don't want to mislead
future developers into thinking that it's not OK to do so if the requirements
have changed.

------
cwmma
the one thing that annoys me about let/const that leads to me occasionally
using var is that with var you can declare a variable in a try block and then
use it afterwards, instead I have to declare a let outside the try or put way
more then I want to in the try.

~~~
dragonwriter
But, why would you want the declaration in the try when the scope of the
variable is broader? It's true that var let's you do that, but it seems to me
that's strictly a misleading thing.

Sure, you’ll often need to split declaration from assignment with let in that
case, but that's not a bad thing, IME.

~~~
madacol

        try {
            const { attribute1, attribute2 } = getObject()
        } catch () {}
        attribute1 // undefined
    

How would you solve that?

~~~
dragonwriter
With let outside the try, because that's the intended scope. Insofar as there
is a problem I see with that, it's that you can't separate declaration of a
single-assignment value (const) from the one allowed assignment, because the
ideal solution would be const declared outside the try with the assignment
inside.

OTOH var declared inside is a bad solution because it's both misleading as to
scope and using a freely-assignable variable for something that's logically
single-assignment. Let outside has only one of those problems.

~~~
madacol
Exactly, I'm just pointing out the limitations of `let/const`

I usually solve that case with

    
    
        let attribute1, attribute2;
        try {
             const object = getObject()
             attribute1 = object.attribute1
             attribute2 = object.attribute2
        } catch () {}
    

But I'm just not satisfied with it, too many statements. And it gets really
messy with many attributes

~~~
decentralised
How about this:

    
    
        let attribute1, attribute2;
        try  {
         ({attribute1, attribute2} = getObject())
        } catch (e) {}

~~~
madacol
wow, didn't know that!

So parenthesis are the trick, thanks!

~~~
decentralised
No problem!

------
amelius
"let" is what I miss in Python.

~~~
mschuetz
Along with actual block scopes.

------
Octoth0rpe
My inner pedant really hates this first sentence:

> There are three ways to create variables in a JavaScript application: using
> var, using let, or using const.

No. There are two ways to create variables (let, var), and _one_ way to create
a constant (const).

~~~
winrid
They're not really constant though, if you wanna be really pedantic. You can
modify a const object for example.

~~~
pfdzm
It’s constant because it cannot be reassigned - but it is not immutable.

~~~
winrid
Right.

------
sunseb
[https://jamie.build/const](https://jamie.build/const)

[https://twitter.com/dan_abramov/status/1208369896880558080](https://twitter.com/dan_abramov/status/1208369896880558080)

~~~
saagarjha
Does JavaScript have value types where const might work the way the first
author expects it to?

~~~
austincheney
No. The only thing that makes _const_ unique from _let_ is that references
declared as constants cannot be reassigned or else an error will be thrown.
The exclusion only applies to the reference name itself and not to any of its
properties as the article articulates.

