const vs let vs var in JavaScript

A chart comparing the similarities and differences between const let and var

Hi! I'm Zac Gordon and I teach JavaScript (among other things). I created this basic site because I often have to reference or explain the differences between var, let and const in JavaScript. Hopefully you find this vide and diagram helpful :)

The Video

Video Transcript

Welcome. In this video, we're going to talk about the keywords var, let, and const. Now, what we're going to do is walk through and compare them point by point across a few different levels because at their basic level of functioning, they're all pretty similar. They all help us define variables. However, there are a few differences between these that are important to know.

So we're going to start off looking at global scope. Now, remember when we work with var variables, we saw in the scope videos that we could access a window object, and window.varname would give us that variable because it's stored in global scope unless we scope it otherwise. So variables or var are always going to be scoped in global scope unless we do otherwise. However, let and const are not going to be stored in global scope.

Now, before we look at what this really looks like in practice, I want to say that that does not mean that let and const cannot be accessed by other pages. For example, in the old way of enqueuing JavaScript, you have an html page and two or three files, like a helpers JavaScript library, and then your app JavaScript library, maybe some other stuff. As long as helpers comes before app, then you can access anything from helpers in it. Now, in that scenario, let and const are still accessible by other files. However, they are not bound to the window object. So let's look at what that looks like.

So here, we're creating a variable, a let, and a const, and we're assigning them different ids. UserId, postId, a siteId, kind of mimicking WordPress, here. Now, if we go to log out window.userId for the variable that works, and that is, although a kind of weird behavior, expected in JavaScript. However, notice that window.postId and siteId are not defined because they're not being stored at that global variable. Now, again, this does not mean that they're not accessible to other files. However, they aren't stored in the global scope, or they are stored in a global scope, we could say, but they're not stored on the window object or on the global window object.

So a little bit of different there, but that is helpful to know how these are different. So you'll often here in JavaScript an argument that you don't want a lot of stuff clouding up or junking up the global namespace, or variables being saved into the global scope, and attached to the window object, and made available more easily to others, and just taking up more space, etc. So, there are some arguments why we wouldn't want things stored in the window object, and let and const are not going to do this, even if they are, we could say, in a global scope.

So next up, we could look at function scope, and all of these work the same across the board, so there's not too much to explain here. If you remember back to working with scopes and functions, if you create a new variable inside of a function, it creates a new scope that is not accessible outside of that function. So in this case, var, let, and const, setting up the same thing, wrapped inside of a function. If we tried to call any of these outside the function, then we would not have access to them. So that works completely as expected. Nothing weird there.

Next up, we have block-level scope. And again, you should remember back to the scope videos, if we do curly braces now in JavaScript, we can have block-level scope, but we have to use let or const. If we use var inside of blocks using curly braces, it's still not going to be scoped and accessible outside of it. So let's take a look at that.

Here, we can see we're doing a simple curly brace block, but this could be a four loop or something like that as well. We have a var, let, and const set up, and we logged them all inside of the block. They all work as expected. However, outside of that block, notice that the var is still accessible, however, the others aren't because they're wrapped inside of that scope and we can't access them outside of it.

So this could be really helpful if you do want to block scope things. However, if you don't, then you'll have to use var in this case.

So, finally, we come to the last major comparison. That is can the value be reassigned? With vars and lets, the answer is yes, and with consts, the answer is no, but sort of no with an asterisk.

Const has what's called immutable binding, but it does not have immutability. To explain the difference between these two, immutability means that once the value is set, you can't change it. So if you set siteId = 1, nobody could change that value again. Now, in const, there's immutable binding, which means that if I set a value equal to a number one, I can't change it again, but if I set a const equal to an object, like a post object, I could go in and change properties within it. Like I could change the postId or the post title, but I couldn't reassign it to be something else or a new object.

That's the immutable binding, and the same thing is with arrays. Once you create an array, you could add and remove items from it, but you can't change it to another array or to an object or something like that.

In practice, let's take a look. We have a const that is a post empty object, we have a const that is a bunch of ids inside of an area, and then we have a const that's equal to just the number one. In this instance, we could compare one to being a string, so numbers in strings are going to behave similarly here.

So in the first example, if we tried to reassign post from an object to be a string, we would get an error, and that error would be this cannot be redefined or reassigned. However, if we tried to reassign post.title, in this case, we're adding a new property in, and we're assigning it, also if we were to try to reassign post.title once it is assigned, that is allowed. So this, again, is the difference between immutability and immutable binding. So post = "Hello World!" is a new string, we'd be trying to change the binding itself, which is not okay. However, post.title is not changing it from being an object. It's just changing values within the object, which is allowed.

And now, this is a point where if you don't want this, you'll have to take things a little bit further, and we'll look at examples and ways of doing that later. However, if your expectation is if you create an object and you don't want that value to be changed, using const alone is not going to be enough.

Now, we could see with ids, this is an array, and we're adding a new item to the end of it, and this allowed. We could also pop items off. We could different things, but we couldn't say ids equal to and then establish a new array like that. We couldn't overwrite the binding.

For example, we'll see here ids is equal to a new array. This would give us an error because we're not adding and removing values from the existing array. We're trying to rewrite it to another one, and const will prevent this and throw an error.

Finally, with id equal to one plus plus is the same as id is equal to id plus one, so really we're just changing the value of it. I could have said id is equal to two or three or turn into a string, etc. All of those would fail.

So at the very basic level, if you want const to be used for a number or a string, it will probably get you the expected behavior, which is once you set up a string like if your site URL is set to a constant, then that would not be allowed to be changed within your application. So that can be really helpful here. However, remember with objects and arrays you migh not get exactly what you're looking for.

So, again, here is the kind of basic comparisons here. Global scope, all, not the same. Function scope, they are all the same. Block scope, they're not the same. And can be reassigned, not the same. So some differences here, which really then raises the question of when do you use which one?

Now, I will say that there is a movement to use const by default and let otherwise. So this is following a principle of strict coding, so be as strict as possible in setting things up, defining what they're going to be, and then not letting them be changed unless they need to be. So by default, if you make everything a const until you realize, "Oh, this is a value that I want to change," then it would become a let. Now, this leads the question of what about var? In this model here, var is being sort of deprecated, and you wouldn't really use it unless you wanted to put something on the window object, or you didn't want something to be block scoped because that's the only ways that they're different from let or const, and you couldn't use one of those to get the same effect.

It's also important to explain that the reason that this direction is happening is because in a lot of other programming languages const, let, and var behave differently than they do in JavaScript. Because it's a little confusing to these developers, it is being moved into a direction of trying to use languages, and terms, and constants that are newer to the JavaScript language so that it can be easier and more familiar for people writing in other languages to move into JavaScript and understand what's going on.

Now, with that said, technically, you could still use var all the time unless you need to otherwise. Even in some of my examples here and in teaching and in other code around you will still see var used. There isn't technically anything wrong with that. Now, there are instances where maybe you want block scoping, or you want some of that prevention for changing the binding or reassigning the value, then you would use const. While this is technically true and you may still see it a bit, I do want to point out that this is not really the direction the JavaScript community is taking. However, I think it's important to keep in mind that they're taking it for ease of use and adoptability, less so because technically var doesn't do the things that you would want to.

You can still look back to that chart, and see that unless you want something to not be in global scope that you want to use block scope or you want to not be able to reassign it, then you could still use var in the same way you have been previously. However, what you're likely to see is most folks defaulting to const, let as a backup, and then var only rarely or really when needed.

That should help you along and help explain a little bit about var, let, and const, and using them in JavaScript.