Var, Let & Const: JavaScript ES6 Feature Series (Pt 1)
Tags: javascript, es6
Published: 2024-06-26 17:42:57

---
title: Var, Let & Const: JavaScript ES6 Feature Series (Pt 1)
published: true
date: 2019-07-28 00:00:00 UTC
tags: javascript,es6
canonical_url: https://www.paigeniedringhaus.com/blog/var-let-const-java-script-es-6-feature-series-pt-1
---

[![Close up of children's blocks](https://www.paigeniedringhaus.com/static/1968bb9b125527906116de9c576a2046/8efd0/blocks-hero.webp "Close up of children's blocks")](/static/1968bb9b125527906116de9c576a2046/de19c/blocks-hero.webp)

## Introduction

The inspiration behind these posts is simple: there are still plenty of developers for whom, JavaScript is a mystery — or at the very least, a little less understood.

Add to that ES6, and the updates that the ECMAScript committee is now planning to release yearly, and it’s a lot of info to keep abreast of.

![Barney head exploding](https://www.paigeniedringhaus.com/2d015acfdb413808a46d93e2426af1bd/barney-gif.gif)

_Sorry, couldn’t help myself — I love Barney from How I Met Your Mother._

I wanted to provide a bunch of posts about JavaScript ES6 features that I use regularly, for developers to reference.

The aim is for these articles to be short, in-depth explanations about various improvements to the language (and how to use them), that I hope will inspire you to write some really cool stuff using JS. Who knows, you might even learn something new along the way. 😄

**For my first post, it makes sense to begin at the beginning with var, let, and const: the building blocks of JavaScript.**

---

## Var

[**`var`**](https://en.wikipedia.org/wiki/JavaScript_syntax#Variables) is the original JavaScript syntax: the OG way to declare a variable, and optionally, initialize it as a value. It’s been around since the beginning of the language, long before ES6 was even a thought in anyone’s head.

Variables have no pre-defined or attached type in JavaScript, meaning any value can be stored in any variable. Some examples:

**Assigning values to variables**

```javascript
var one = 1; // the integer 1 has just been assigned to the variable one

var two = 'two'; // the string 'two' has been assigned to the variable two

var paige = {
  gender: female,
  hairColor: red,
  eyeColor: blue
};
// the object containing a person's traits has been assigned to the variable paige
```

All of the `var`s above are valid examples of how JavaScript allows any value to be assigned to any variable, unlike strongly typed languages like Java, which (until recently), required all variables be declared and typed before compile time.

Another thing to know about `var` is that it is regardless of if it is globally or locally scoped, these variables can be re-declared and updated at will. Check out this perfectly valid example.

**Reusing the same variable with different value types**

```javascript
var greet = "Hello there";
console.log(greet); // prints: "Hello there"

greet = true
console.log(greet); // prints: true

greet = 11;
console.log(greet); // prints: 11

greet = welcome = (name) => { 
  return `Hi ${name}. Welcome!`
};
console.log(greet("Paige")); // prints "Hi Paige. Welcome!"
```

Although I reused the existing variable `greet`, JavaScript throws no error, regardless of whether the variable is a string, a boolean, an integer — heck, even a function.

### Variable declarations, lexical scoping, and hoisting

There are a few things to be aware of (which have tripped up many a developer, myself included), when using `var`. These types of variables are **"lexically scoped"** and subject to what’s known as **"hoisting."**

What this means in execution is that a `var`-type variable, no matter where it is defined inside of a block of code, will be pulled to the top of its scope before code execution. For example, if you wrote a few lines of JavaScript, then declared `var tree = "elm";`, at run time, behind the scenes, var tree would be "hoisted" to the top of the scope where it was defined.

It may not be assigned to the value of `"elm"` until several lines later, but the variable would exist according to the JavaScript engine. Here’s an example to show how this works, and what it could mean.

**Variable declaration versus variable assignment in JavaScript**

```javascript
var greeter; {/* the JS engine knows greeter is a variable, 
but it doesn't know what value greeter has */}
console.log(greeter); // currently, greeter prints: undefined

greeter = "say hello"; // now, greeter's been assigned to the value "say hello"
console.log(greeter); // prints: "say hello"
```

Lexical scoping also comes into play here. Without going too much into the details of lexical scoping in JavaScript (because that’s a whole other blog post), the word “lexical” refers to the fact that lexical scoping uses the location where a variable is declared within the source code to determine where that variable is available.

This boils down to if a variable is created in the global scope, it’s hoisted to the top of the global scope, if the variable is created within a function, it’s hoisted to the top of the function, and so on and so forth.

Here are examples of variable hoisting and lexical scoping in action as the JavaScript engine runs.

### Variable hoisting based on lexical scoping

```javascript
var something; // declaration is hoisted to the top of the global scope
console.log(something); // prints: undefined

function doAnotherThing() {
  var anotherThing; {/*} declaration is hoisted to the top of the function's 
  lexical scope but not immediately assigned a value */}
  var thisOneThing = "a defined value"; // this variable is hoisted and then immediately defined

  function useAnotherThing(anotherThing) {
    console.log(`The value of another thing: ${anotherThing}`);
  }

  function useThisOneThing(thisOneThing) {
    console.log(`The value of this one thing: ${thisOneThing}`)
  }

  useAnotherThing(anotherThing); 
  {/* prints: "The value of another thing: undefined" because the variable 
  wasn't assigned a value until AFTER the function useAnotherThing() ran */}

  anotherThing = "an undefined value"; 
  // finally the variable, initialized earlier, is assigned a value

  useThisOneThing(thisOneThing); 
  {/*} prints: "The value of this one thing: a defined value" because 
  the variable was assigned a value before the function useThisOneThing() ran */}
}

something = "that thing";

console.log(something); // prints: "that thing"
console.log(doAnotherThing()); // see printouts above next to inner functions
```

In the example above I show how the variables `something` and `anotherThing`, by not being immediately assigned values after being declared are `undefined` when `console.log()` is called on them. Once their values are set further down the script and `console.log()` is called again, they print their values to the console.

The variable `thisOneThing`, however, is initialized and assigned a value immediately after initialization, meaning that when the function using it: `useThisOneThing()` is run (which is also an example of a JavaScript [**"closures"**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) at work), it prints out the string `"The value of this one thing: a defined value."`

I think this is enough about `var` and how it works. There’s a million other tutorials talking about it, too. Now, let’s get on to the exciting, new ES6 variable syntax, and how these types of variables are different.

## Let

[**`let`**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) was finalized and officially introduced for widespread use with the release of ES6 in 2015. Of the two new variable types introduced, it is the much more flexible and ephemeral of the pair.

### Let's similarities to var

While let is a totally new variable type, it does have share a couple of commonalities with `var`. For instance:

- When `let` is initialized, it can optionally be assigned a value at initialization time,
- `let` is also a variable type that can be mutated and / or reassigned to different data types at run-time.

And that’s pretty much where the similarities end.

### Let's differences to var

Ok, here’s where it gets interesting and `let` begins to differ from `var`.

### Block scoping and variable declaration and assignment

`let` is block scoped to the statement, or expression within which it is used, unlike `var`, which defines a variable globally, or locally to an entire function regardless of block scope.

Bottom line: `let` lives inside a chunk of code (usually) defined by curly braces like so `{}`.

Additionally, `let`’s value can be updated but not redeclared as a new variable inside of the same scope, which `var`-type variables can. There’s an example below showing the differences between `let` and `var`.

**Valid assignments of let based on block scoping**

Here is a valid example of assigning the variable greeting using the let keyword in the same file, but in different block scopes.

```javascript
let greeting = "say Hi"; // one variable declared in the global scope

if (true) {
  let greeting = "say Hello instead"; 
  {/* another variable of the same name declared within this inner, block scope */}
  console.log(greeting); // prints "say Hello instead"
}
console.log(greeting); // prints: "say Hi"
```

**Invalid assignments of let due to block scoping**

Since this `let greeting` variable is assigned a value in the global scope, it cannot be redeclared and reassigned to a new value within the same scope. If this scenario occurs, it throws a `SyntaxError` in the console.

```javascript
let greeting = "say Hi";
let greeting = "say Hello instead"; //SyntaxError: Identifier "greeting" has already been declared
```

Doing the same type of thing with var produces no such error.

```javascript
var fruit = "banana";
console.log(fruit); // prints: "banana"

var fruit = "pear";
console.log(fruit); // prints: "pear"
```

### Variable hoisting (or lack thereof) and global objects

Hoisting does not apply to `let`. Unlike `var` a `let`-type variable won’t be initialized to `undefined` _before_ its definition gets evaluated by the parser.

If you try to use a `let` variable before the part of the code where it’s initialized, you’ll get a `ReferenceError` thrown.

**ReferenceError of let because it was called before parsed**

```javascript
console.log("test 0", test)

let test; // prints: ReferenceError: test is not defined
```

And at the top level of programs and functions, `let`, unlike `var`, does not create a property on the global `window` object when declared in the top-most scope either. It’s not necessarily a bad thing, it means less pollution of the global namespace, which we can all benefit from, but it also means you can’t use the oft misunderstood `this` property to access said global variables either.

**No global object properties with let**

```javascript
var x = "global";
let y = "global";

console.log(this.x); // prints: "global"
console.log(this.y); // prints: undefined
```

Ok, I think that’s enough about `let`, it’s time to move to the stricter, more immutable variable type `const`.

## Const

[**const**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) came about in the same ES6 release as `let` back in 2015. But where `let` provides increased flexibility and less permanent variables, `const` provides more rigidity and permanence.

It is also, by far, the most different of the three variable types.

### Const's defining traits

This variable declaration shares some things with let.

- `const`, too, is limited to block scoping,
- It does not create properties on the `window` object when it’s created in the global scope,
- When it is declared it must also have a value assigned to it,
- And it is not hoisted at run time.

### Block Scoping

Const has the same type of block scoping that `let` does, but once `const` is used to declare a variable, that value can’t be changed through reassignment or redeclared within that scope.

**const reassignment TypeErrors and redeclaration SyntaxErrors within the same scope**

```javascript
const pet = "dog";
console.log(pet); // prints: "dog"

pet = "cat"; // TypeError: Assignment to constant variable
console.log(pet);

const person = "Sean";
const person = "George"; // SyntaxError: Identifier "person" has already been declared
```

Both pointing the existing `pet` variable towards a different value or trying to redeclare `person` within the same scope results in errors in the console.

But with block scoping in mind, the following examples work with no issues.

**Valid block scoping of variables using const**

```javascript
const pet = "dog";
console.log(pet); // prints: "dog"

if (true) {
  const pet = "cat"; // TypeError: Assignment to constant variable
  console.log(pet); // prints: "cat"
}

const person = "Sean";
console.log(person); // prints: "Sean"

function meet() { 
  const person = "George"; 
  console.log(`Meet ${person}`);
}
console.log(meet()); // prints: "Meet George"
```

### Immutability (sort of)

`const` creates a _read-only_ reference to a value. The caveat to that statement though is the value itself is mutable, but `const`, once assigned, cannot be reassigned.

If `const` is assigned to an object, the properties within that object can still be updated and changed.

**const’s reference to an updatable object**

```javascript
const greeting = {
  message: "Hello there",
  person: "Paige"
};
console.log(greeting); // prints: { message: "Hello there", person: "Paige" }

greeting.message = "Hi there";
console.log(greeting); // prints: { message: "Hi there", person: "Paige" }
```

### Simultaneous declaration, initialization and no global object

Global constants like `const` do not become properties of the `window` object, unlike `var` variables. An initializer for a constant is also required; that is, you must specify its value in the same statement in which it's declared (which makes sense, given that it can't be changed later).

**const not polluting the global scope with object properties**

```javascript
var x = "global";

const y = "global";

console.log(this.x); // prints: "global"

console.log(this.y); // prints: undefined
```

If `const` is not assigned a value when it is initialized it will throw a `SyntaxError`. Likewise, if a script tries to invoke it before the parser has reached the variable, it will throw a ReferenceError just like `let` because `const` is not subject to hoisting and it cannot be set to `undefined` before being assigned a value.

**Errors From calling variables before declaration or initializing with value assignment**

```javascript
console.log(fruitTree); // ReferenceError: fruitTree is not defined

const fruitTree = "fig tree";

const tree; // SyntaxError: Missing initializer in const declaration
```

And that is about all there is to know about `const`, as well.

---

## Conclusion

The JavaScript language has been around for more than 20 years and even ES6 has been out since 2015, but even so, there’s still plenty of misconceptions and knowledge gaps about it.

My aim of this series is to dispel those myths and give you a better understanding of JavaScript, and introduce some of the ES6 syntax you may use everyday but not fully grasp the nuances of.

Since everything in JavaScript is built around variables, it seemed like an appropriate place to start with `var`, `let`, and `const`.

Check back in a few weeks, I’ll be writing about JavaScript, ES6 or something else related to web development.

If you’d like to make sure you never miss an article I write, sign up for my newsletter here: https://paigeniedringhaus.substack.com

Thanks for reading, I hope you learned something new about the most basic building blocks of JS: the humble variables. Please share this with your friends if you found it helpful!

---

## References & Further Resources

- [Var, MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var)
- [Let, MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)
- [Const, MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)
- [JavaScript syntax, Wikipedia](https://en.wikipedia.org/wiki/JavaScript_syntax)