DEV Community

Paul Thompson
Paul Thompson

Posted on • Updated on

3 reasons to use 'var' in JavaScript

The var keyword was JavaScript's first way to declare a variable. It fits, right? Var, variable, it's in the name. But like the Joker, var is more than pretty face -- it has some baggage. As a beginning programmer, or a seasoned one dipping your toe into the seedy underbelly of JavaScript development, you maybe be wondering when you should use var to declare your JavaScript objects and functions.

Never fear. I have 3 reasons for you to use var in your next JavaScript project.

You love tradition and spurn anything new

Var may be the oldest keyword to declare a variable, but it is by far the only one. It's younger cousins, let and const exploded onto the scene with ES6 (over 6 years ago as of this writing!). But if sticking to old norms fraught with perils is your thing, keep using var and leave these upstart keywords to listen to their terrible pop music and complain about their parents.

You prefer mutability, even when you don't

Var has the troubling distinction of creating a variable of any type, which can then be changed to a variable of any type later. That's right, the number you declared on line 4 just became a string on line 17 and a boolean on line 109. This type flexibility is a key feature of JavaScript, but it can be avoided. But if you too like to live dangerously, keep using var.

You like leaky scopes

Prior to ES6, JavaScript variables were always defined at the function scope. In a lot of cases, this meant variables were global. JavaScript didn't enforce block-level scopes such as inside a for loop or if block. So a variable declared with var would be hoisted to the top of its function scope. In other words, the variable declaration moved to the top of the current lexical environment with a value of undefined. A common issue arising from hoisting is that such variables are accessible outside the block scope, where the developer may not expect them to be.

A subtler and more difficult to detect bug can happen here as well, variable shadowing. Rarely this may be desired. If that is you, var is your hero.

There must be a better way

If you made it this far, you're probably seconds away from pounding out a fierce comment about how I'm wrong about var. The truth is, no one should be using var in any JavaScript code except for a history lesson. Even then, it should come with a footnote that says something like, "please don't ever do this."

Let and const have been available in every major browser for the last 6 years. This is really, really ancient in frontend years. var isn't just the parent misunderstanding their teen, it's the great grandparent everyone loves but no one invites to the fun parties.

Let retains JavaScript's flexible type system while enabling block-scoping. Const creates a -- you guessed it -- constant variable in block-scope. Const creates a variable that cannot be reassigned, but similar to most other languages, const objects can have their properties mutated. These two alternatives to var should cover every use case you have. Even if you are in the tough spot of needing to support truly archaic browsers, don't use var. Use a tool such as Babel.

So please, please, do not use var.

Discussion (63)

Collapse
lukeshiru profile image
LUKESHIRU

I fell in the click-bait trap! I was about to write a comment about why you shouldn't use var until I started reading 🤣 ... Indeed, nowadays there's no excuse to use var instead of let or const.

Collapse
paritho profile image
Paul Thompson Author

And yet I keep seeing it time and time again in tutorials. Sad.

Collapse
thumbone profile image
Bernd Wechner • Edited on

All language updates take time to trickle through. It is the way of the internet. I mean search the web with any technical question and rail, as most of us do, at any articles that are not presenting their publication date clearly, as stuff simply gets dated but still always found. I think we'll be reading Python 2 solutions to problems on web search results for years to come yet for example ....

Thread Thread
digitaldevourer profile image
DigitalDevourer

Hate when that happens.
You're ½ way through when things start to feel off, and now it's become a hunt for the date.
Worst of all are the "SEO-based" articles that update their titles or keywords to match popular searches, despite having almost no related content or are years too late.

Collapse
emptyother profile image
emptyother

6 years is nothing! I've seen PHP tutorials with methods 18 years past deprecation.

Thread Thread
lukeshiru profile image
LUKESHIRU • Edited on

Let me fix that for you:

6 years is nothing! I've seen PHP tutorials! 🤣

Collapse
baenencalin profile image
Calin Baenen

My school uses Code HS with this dog named Karel, and a pet peeve of mine is that they use var.
The teacher doesn't even address them, as they basically have no education on the language itself (they're just permitted and appointed to teach it).

Even as someone who barely uses JS, this annoys the fuck out of me.

Collapse
darkwiiplayer profile image
DarkWiiPlayer

Same here, I also came here looking for outrage but then read the headings :D

Top tier clickbait

Collapse
getify profile image
Kyle Simpson
Collapse
lukeshiru profile image
LUKESHIRU

One thing I don't quite get about the points being made there is that they complain about this:

let greeting = "Hi!";

{
    // what should print here?
    console.log(greeting);

    // .. a bunch of lines of code ..

    // now shadowing the `greeting` variable
    let greeting = "Hello, friends!";

    // ..
}
Enter fullscreen mode Exit fullscreen mode

Because we get an error, but my question is: In which scenario is desirable to have a shadowed variable that we assign after is used? That code above is actually preventing bugs:

  1. The dev maybe wanted to use the external greeting and got confused, the error will help with that.
  2. The dev maybe wanted to use the internal greeting value, the error will help with that too.

So, to fix 1 the dev could:

let greeting = "Hi!";

{
    // This prints the external `greeting`
    console.log(greeting);

    // No more shadow, the above code works, no errors.
    let longGreeting = "Hello, friends!";
}
Enter fullscreen mode Exit fullscreen mode

And to fix 2:

let greeting = "Hi!";

{
    // Moved shadow to the top
    let greeting = "Hello, friends!";

    // This prints the internal `greeting`
    console.log(greeting);
}
Enter fullscreen mode Exit fullscreen mode

In both scenarios, the greeting in the upper scope is not being changed, which is ideal because we are writing code that declares a new value, we shouldn’t be changing pre-existing code. If you really want to change the original value of greeting, you need to be more explicit about it (which is great):

let greeting = "Hi!";

{
    // This prints the value of `greeting` in the upper scope
    console.log(greeting);

    // Change value of upper scope `greeting`
    greeting = "Hello, friends!";
}

// Out here `greeting` has a new value now
Enter fullscreen mode Exit fullscreen mode

Is there any scenario in which that is bad from your point of view? I would personally take that behavior over var's any day. With var:

var greeting = "Hi!";

{
    // This will print "Hi!"
    console.log(greeting);

    // Maybe you want to do something with this, maybe you don't
    // we'll never know...
    var greeting = "Hello, friends!";
}

// Oops `greeting` out here now is "Hello, friends!"
Enter fullscreen mode Exit fullscreen mode

I agree that var was never broken, but Function.prototype isn't broken either, and folks prefer to use class. Nobody said var is broken, it just has a different way of dealing with scope and hoisting that is worst than "the new thing". You can change every use of let and const with var, but why would you? You could also use Function.prototype pretty much in every place you're using class but you wouldn't. I also agree that const has limited utility, but still it has at least some utility. Ideally it should make objects immutable, yes, but that doesn't mean that because it doesn't has that is suddenly worst than var. Going back to the examples above, if you declare the upper scope greeting as a const then you get an error when you try to change its value, so if the idea was to avoid changes in the upper scope string, const gave you something that you didn't had with var or let.

TL;DR: I agree var was never broken, but the utility we get from let and const make them a little more useful, and that little is enough to use them over var from my point of view.

Cheers!

Collapse
getify profile image
Kyle Simpson

I don't think I hardly ever would take advantage of variable hoisting in this way:

x = 2;

// later:
var x;
Enter fullscreen mode Exit fullscreen mode

I agree that's problematic. But I don't want the language to complain at me, I want a configurable linter to complain at me. That's my objection to these errors. The language doesn't need to be my nanny. I am perfectly capable of choosing what rules I want enforced or not. And if it's a configurable and extensible tool, I can extend it to understand more nuances to when I want to allow disallow things. Once you bake an error enforcement into the language, you force that opinion on everyone, forever.

Moreover, there's many other ways that hoisting (and var) ARE helpful. For example:

try {
   var x = whatever(42);
}
catch (err) {
   var x = "oops";
}

console.log(x);
Enter fullscreen mode Exit fullscreen mode

Here, the try..catch construct is an "accidental" scope... IOW, I never intended it to be a scope. If I use let inside it, it becomes a scope when I don't want it to be. If I use let outside the block statement, I have to separate my declarations from my initial assignments, which I rarely like to do.

Another example:

do {
   var x = whatever(42);
}
while (x < 100);
Enter fullscreen mode Exit fullscreen mode

I generally prefer the loop to be treated like its own scope, but unfortunately, the while condition is not inside that scope, so I need the x to be in an outer scope. But it doesn't make any sense semantically to declare it there, since it belongs to the loop.

And also "function hoisting" is useful, for example in cases like this:

fn = wrapWithSomeBehavior(fn);

// later:
function fn(whatever) {
  // ..
}
Enter fullscreen mode Exit fullscreen mode

There are a variety of other edge cases and uses. But in summary: there are perfectly valid uses of var (or hoisting in general) that are not just stylistic preference or semantic in nature, but also functionally more desired.

We should use var when it's helpful, use let when it's helpful, and (occasionally) use const if we really must.

Thread Thread
lukeshiru profile image
LUKESHIRU • Edited on

I get where you're coming from, but I don't see myself "opting out" of those errors, so having just a linter for that doesn't feel quite right. Taking your snippets as examples:

try {
    var x = whatever(42);
} catch (err) {
    var x = "oops";
}
Enter fullscreen mode Exit fullscreen mode

I read the above as try to declare x with the output of whatever, and if it throws, then declare x with another value. I instantly think that you actually meant to write "Assign the output of whatever to x, or "oops" if it throws, and to express that we can just use let:

let x;

try {
    x = whatever(42);
} catch (err) {
    x = "oops";
}
Enter fullscreen mode Exit fullscreen mode

Same for the while, I read your code as "declare x with the output of whatever", when I actually think that you wanted to change the value of x in every loop like this:

let x;

do {
    x = whatever(42);
} while (x < 100);
Enter fullscreen mode Exit fullscreen mode

And about your point with function hoisting, I'm one of those folks that prefer to use things after those things are defined, so I would never write code like:

fn();

function fn() {}
Enter fullscreen mode Exit fullscreen mode

I generally write the function first, and then I use it, so it would look more like this:

const fn = () => {};

fn();
Enter fullscreen mode Exit fullscreen mode

And I generally use const because once I create declare a function, I don't have any intention of changing that declaration at runtime, so receiving an error if me or someone else tries to do fn = wrapWithSomeBehavior(fn) is valuable for me.

Thanks for taking the time to reply, Kyle! I follow your work since I read one your posts in David Walsh blog (I used to be a fan of MooTools back in the day, so I followed David's work closely), and I find extremely useful to have this kind of dialogs with folks like you!

Cheers!

Thread Thread
getify profile image
Kyle Simpson

Here's the thing: you're entitled to your opinions on these things and I'm entitled to mine. I strongly disagree with every point you just made. But that doesn't really matter. Neither one of us is "right". So why should the language codify one set of opinions and make life harder for those who don't agree? Tools are where opinions belong, not languages.

Thread Thread
lukeshiru profile image
LUKESHIRU

Yup, I get it, that's why I mentioned that I find it valuable (and it seems there are lots of folks that do too). The good thing is that you still have var if you want to code with your style, and I can just avoid var to code with mine.

And to be completely honest, I don't like "throwing" in general, I prefer other ways to handle errors, so in that regard I also agree with you that at least using let/const "wrong" shouldn’t throw.

Collapse
lonyyy profile image
lonyyy

lmaoo your explanation is more complete than the actual article

Collapse
sabbakilam profile image
SabbaKilam

Thanks for the rational clarification. Nuanced treatment of this topic is rare.
I've never liked const. I'll start using var again for function scoping.

Collapse
sabbakilam profile image
SabbaKilam

Thanks for the rational clarification. Nuanced treatment of this topic is rare.
I've never liked const. I'll start using var again for function scoping.

Collapse
dagr8 profile image
DAGr8

Cancel VAR
The cancel culture is real. ;p

Collapse
raibtoffoletto profile image
Raí B. Toffoletto

Ufff.... I came here hoping that the title was sarcastic, but for a moment in the first paragraph I worried that you were REALLY to defend VAR.... 🤣. Nice writing 👍 and let's all chant "die VAR, die...."

Collapse
koire profile image
Koire

Var is actually used a lot in enterprise

Collapse
lukeshiru profile image
LUKESHIRU

Don't be that guy. We all know that "enterprise" have lots of deprecated stuff, but still that doesn't justify using it. Just because there are some banks still using COBOL, that doesn't mean you should learn it.

Thread Thread
koire profile image
Koire • Edited on

We don't always write var but for IE but we definitely transpile it
I still have projects that warn you you need IE 5 or later for it to work correctly.

Edit
There is the case where someone might come in and say "var bad" and use replace to turn them all to let or const and break everything in a legacy system because it was being funky

Collapse
raibtoffoletto profile image
Raí B. Toffoletto

I'm not saying to go back and alter legacy code, but in 2021 you should not be writing JS with var... enterprise is a ship difficult to steer, but you can do it slowly. I don't shame on my colleagues still using jQuery to build stuff, but you can use const and let with jQuery.

Collapse
thebearingedge profile image
Tim Davis

I teach var first because:

  1. It's still out there and I don't want my students seeing it at work and thinking "why didn't my teacher tell me about something so basic?"
  2. It behaves differently from let and const and it's completely different to have a pure academic or a "theoretical" understanding of something and having real hands-on (for more than an hour or some tweet's worth of words) experience with something.
  3. Knowing about and being competent when dealing with all three is better than knowing about and being competent when dealing with only two of the three (66% is a D, great job).
  4. Block scoping is a good transform output to demonstrate when teaching Babel.
  5. I ask for let and const to be used later in my curriculum where appropriate.

I don't really know who this article is for, but sadly it seems to encourage ignorance in exchange for cool coins.

Collapse
lukeshiru profile image
LUKESHIRU

Did you teach them about eval, with and other old stuff as well? I mean I get that you want to teach old stuff for context, but you should be very clear about avoiding var. Babel no longer does those transformation from let and const to var unless you explicitly configure it to do so. Go and check the Babel REPL.
I agree we should know about var, but one thing is knowing about it and other is actually using it.

Collapse
thebearingedge profile image
Tim Davis • Edited on

Did you teach them about eval, with and other old stuff as well?

that's not really what this is about.

I mean I get that you want to teach old stuff for context, but you should be very clear about avoiding var.

I've yet to hear any real argument for this.

Babel no longer does those transformation from let and const to var unless you explicitly configure it to do so. Go and check the Babel REPL.

I addressed this already.

I agree we should know about var, but one thing is knowing about it and other is actually using it.

My point is that you don't know something unless you have used it.

Thread Thread
lukeshiru profile image
LUKESHIRU

I mean I get that you want to teach old stuff for context, but you should be very clear about avoiding var

What I meant by that is that I get that you teach that to give them context about how we used to do stuff with var, including examples or even exercises with it. But My point is that the same way you could teach eval, you need to be super clear about the limitations and problems it has. Maybe even center the exercises you give to your students in this problems so they struggle with them and when you present let and const, they see why are they appealing to devs nowadays.

About your answer:

I've yet to hear any real argument for this.

Several where made in this article already, but it boils down to your coding style. For mine, let and const are way more useful than var, so I avoid var and in my personal projects I have linting rules against it. There are folks with other coding styles that rely on hoisting, redeclaration and leaky block scopes that benefit from var, so for them it makes sense to do the opposite and stick to var and maybe even ban let or const in their linting rules.

One thing is clear, and is that is way more popular to prefer let/const, but the good thing is that if you don't, JS is designed to "not break old code", so you can just stick to var forever if that's what you prefer.

Thread Thread
thebearingedge profile image
Tim Davis • Edited on

For mine, let and const are way more useful than var, so I avoid var and in my personal projects I have linting rules against it.

Same here. But I teach beginners and coding style is the least of their worries and they need to be prepared to slot into the team they're hired onto.

There are folks with other coding styles that rely on hoisting, redeclaration and leaky block scopes that benefit from var, so for them it makes sense to do the opposite and stick to var and maybe even ban let or const in their linting rules.

This is an interesting observation that I've seen as well. IME, they just write sloppy or confusing code in general. It's always possible to write code that avoids the pitfalls of var entirely as long as the style is reasonable. What's weird is that the style of my reference solutions function identically when you refactor them to the "right" way and use const / let. This is probably why it's so rare for my students get "tripped up" by the pitfalls of var. When they do, the code they're writing makes no sense anyway, which is expected of beginners.

One thing is clear, and is that is way more popular to prefer let/const.

Yes, you are absolutely right, which is why they're also equipped for that. The motivation behind my comments also boils down to your point. There are social pressures and media being produced that discourage thinking critically about how things work, and when they're appropriate. Often things get reduced to memes and jokes and if I "warn" them about anything, it's that they're going to encounter people, videos, and writings that are reductive and unproductive. They need to be careful not to trick themselves into thinking they're any better at building useful software by "agreeing" with anybody's lopsided opinions.

Collapse
getify profile image
Kyle Simpson

I taught eval and with for years, specifically so people understood why they shouldn't be used.

Collapse
mtrantalainen profile image
Mikko Rantalainen • Edited on

The only reason to use 'var' is to be compatible with some old info tv systems which have some weird more or less broken HTML renderers. There you cannot use any automated tools either because nobody really wants to support those things so you have to write fully custom implementations. If you don't need to support such things you shouldn't use 'var' anymore.

Collapse
emptyother profile image
emptyother

Two "good" reasons I still use var:

  • ~Old projects that need to support IE11 and isnt transpiled.~ Oh, right, even IE11 supports let and const. Well almost, it still have a few gotchas that will never be fixed.
  • I'm also writing C# and var is stuck in my fingers. Sometimes I even miss the eslint warnings about it. Darn muscle memory.
Collapse
aequinn profile image
Anthony Quinn

Number 3: kind of like old projects, you are doing any JavaScript variables in Google Tag manager, they still force you to use var, I develop the scripts with the new and am forced to roll it back to the old when try to save.

Collapse
darkwiiplayer profile image
DarkWiiPlayer

A friend was learning JS at school until not long ago, and they were still learning var, HXR and function (as in, unscoped function declarations that end up in window by default).

Collapse
andyhilton profile image
Andy Hilton

Why didn't let just replace var? If the whole world is against it why does it still exist?

Collapse
paritho profile image
Paul Thompson Author

The EcmaScript committee has strict guidelines to 'not break the web'. Meaning, old JS code must always work.

Collapse
koire profile image
Koire

Also let is scoped

Collapse
emptyother profile image
emptyother

Nobody want to dig up and rewrite their 10 year old production code. But eventually it too will go the way of elem.attachEvent() and the <blink> tag.

Collapse
matttepp profile image
Matyáš Teplý

They had us in the first half, not gonna lie.

Collapse
sabbakilam profile image
SabbaKilam

I always use var at the browser's console so that I can re-declare and re-assign variables at will, hassle-free, while playing around and testing concepts. Otherwise, I get clobbered with error messages and restrictions.

Collapse
lukeshiru profile image
LUKESHIRU

In recent versions of Chrome, you can "redeclare" const and let in the console 🎉

Collapse
andrebradshaw profile image
Andre Bradshaw

Let and const are useful, but when people say var should never be used, I immediately start to question if they have done any interesting development in JS.

Additionally, for beginners, I would argue that using var forces people to deal with unexpected behaviors which is a useful method for actually learning how JS works.

Collapse
yamanidev profile image
Mohamed El Amine Yamani

As soon as I read the title, I didn't give a damn if it was a clickbait or not, I am reading this anyway xD. I like the humor, keep it up!

Collapse
meliodas profile image
Henry Onyango

There are reasons to still use var. There's nothing with var. It's not broken. It's important you understand how it works and when is most appropriate to use it.

Collapse
paritho profile image
Paul Thompson Author

I'd be interested in hearing when it is appropriate to use it

Collapse
meliodas profile image
Henry Onyango

Look at the section "making the case for var"
github.com/getify/You-Dont-Know-JS...

Thread Thread
lukeshiru profile image
LUKESHIRU

The author of the book is in the comment section as well. His point is mainly that if you have a certain coding style, var is better than let and const, and if you have other style, let and const are better. What we agree on is that it shouldn’t throw.

Thread Thread
mustapha profile image
Mustapha Aouas

I strongly disagree with every point you just made

I don’t think he agrees on anything with you.

Cheers!

Thread Thread
lukeshiru profile image
LUKESHIRU

Gotta love quotes without context.

Collapse
koire profile image
Koire

Don't forget code golf!
Let's scope is more constrained than var, so you (maybe) can't do as many tricks with let as var.
And const is 2 more characters! That's unforgivable

Collapse
paritho profile image
Paul Thompson Author

There are actually a lot of really cool exploits you can do in JS because of it. Golf coding is amazing!

Collapse
thumbone profile image
Bernd Wechner

Love the faux title ... ;-)

Collapse
fyodorio profile image
Fyodor

Anything can be a weapon in hands of a mighty ninja...

Collapse
abhishekraj272 profile image
Abhishek Raj

What do you think babel does to your let and const 🙃

Collapse
lukeshiru profile image
LUKESHIRU

Let them as they are? FYI let and const are supported on all major browsers, so transpilers like babel don't turn those into var unless you specifically change the config to target old browsers... and even if that's the case, the idea with Babel is to write modern code that is translated to legacy, so if Babel turned those into var, that still isn't a valid reason to not use let and const.

Collapse
synrec profile image
Synrec

Unfortunately the engine I use for my project means I have to use var.

Have gotten rather creative in avoiding overlaps in var names tho.

Collapse
morewry profile image
Rhy Moore

What about hoisting?

Collapse
gab profile image
Gabriel Magalhães dos Santos

don't underestimate var, it was the first global storage concept in javascript lol

Collapse
gitcommitshow profile image
gitcommitshow

You're redefining the click-bait. Nice article.

Collapse
peteole profile image
Ole Petersen

And next week: 3 reasons to use PHP!

Collapse
cnsknight profile image
Codename: Steeve Knight

Inexcusable lack of editing here. I could not get past the second paragraph!

Collapse
dominuskelvin profile image
Kelvin Omereshone

If you know the why, you can live any how.
— Friedrich Nietzsche

Collapse
fmontone profile image
Fabio Montone • Edited on

Yeah! Cool click -bait and I was fairly trapped! Was ready to vomit a fierce comment and let the community know how I'm sharp with JS!
🤣🤣🤣🤣🤣🤣🤪 Cheers!

Collapse
mleandrojr profile image
Marcos Leandro

I fell in the bait!
It's a great article.