let var be const
Tags: javascript, coding
Published: 2017-12-12 00:21:54

---
title: let var be const
published: true
description: Ways to define your variables
cover_image: https://thepracticaldev.s3.amazonaws.com/i/2v9l1a3yckovspi4vjeb.jpg
tags: javascript, coding
---

_[Cover image by Christiaan Colen on Flickr](https://www.flickr.com/photos/christiaancolen/)_

With ES2015 JavaScript got a bunch of new features, two of them being `let` and `const` keywords that let you declare your local variables.

## `var`

Variables you declare with `var` will be scoped to the function they were declared in.

This means, even if you declare them in nested blocks _(other curly braces)_ inside of a function, they will _still_ be scoped to the function.

For example, if you declare it inside of a try block like this:

```javascript
    function f(x) {
      try {
        var y = x.toString();
      } catch(e) {
        return "";
      }
      return y;
    }
```

It will actually be declared like that:

```javascript
    function f(x) {
      var y;
      try {
        y = x.toString();
      } catch(e) {
        return "";
      }
      return y;
    }
```

Every `var` declaration will be _hoisted_ to the top of the function. This is why it is considered a `best practice` to declare `var`s at the top of a function, it will end up there anyway.

If you want to scope a `var` to a code block, you would have to fill or replace it with a function expression and call the function right after definition. 

```javascript
    function f(x) {
      var y;
      if (x >= 0) (function() {
        var z = Math.random() * 10;
        y = x * z;
      })();
      return y;
    }
```

The anonymous function has access to `f()`s local variables, so it can use `y`, but `z` is only defined inside of the anoynmous function and can't be accessed inside `f()`.

As you can see, this is rather sub-optimal, but this was _the way_ for many years. If you are bound to use ES5 and for some reason can't use a compiler like Babel, you still have to do this.

## `let`

The `let` keyword is now a way to declare variables that aren't scoped to a function, but to a block. This means any code enclosed by curly braces _confines_ that variable.

```javascript
    function f(x) {
      let y;
      if (x >= 0){
        let z = Math.random() * 10;
        y = x * z;
      } else {
        y = 10;
      }
      return y;
    }
```

In this example `z` is only accessible inside the `if`-branch, the `else` branch or the rest of `f()` could not access it.

Blocks can alse be used without any statement.

```javascript
    function f(x) {
      let results = [];

      // first calculations
      {
        let a = 10 * 10 * x;
        let b = a * Math.PI;
        results.push(b);
      }
      
      // second calculations
      {
        let a = 3 + 2 + x;
        let b = a * a;
        let c = a + b;
        results.push(c);
      }
   
      return results;
    }
```

This allows to structure code and scope variables to the part of the function they are used. As you can see, the blocks have access to the outer scope variables `results` and `x`.

## `const`

So what is the `const` keyword about? Well, you may have seen it in other languages like C or Java. In JavaScript it declares a variable that can't be changed, but _be careful_ this only applies to the direct content of that variable. Otherwise it scopes as `let`.

This won't work:

```javascript
    const a = 10;
    a = 11;
```

These on the other hand will:

```javascript
    const a = [1, 2, 3];
    a.push(4);

    const b = {x: 10, y: 20};
    b.z = 30;
```

To prevent objects (arrays are objects too) from being changed, you need to `freeze` them `manually`, which impacts performance.

This will throw an error:

```javascript
    const a = Object.freeze([1, 2, 3]);
    a.push(4);
```

## When Use What?!

I try to use `const` as much as possible, if functions get bigger, it often gets cumbersome to find out how often and where a variable was changed on the way down.

Sometimes it helps to use `let` with `try/catch`, because I have to set a variable inside `try` and it needs to be accessible after the `try`.

I avoid `var` completely nowadays. `const` and `let` have the same scoping, their only difference is their write-access, so it's easy to reason about them interchangably. `var` on the other hand works much different from them and I think it just makes stuff more complicated when mixed.