Hoisting - One of the trickiest Javascript features
Tags: javascript, es6, dev
Published: 2019-08-18 18:46:43

---
title: Hoisting - One of the trickiest Javascript features
published: true
description: 
tags: javascript,es6,js,dev
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ag3vd48eh04f7t2ydpz1.png
---


Javascript is a programming language that can be tricky for beginners. Once you understand how it works, it becomes clear, but in the beginning, you end up debugging problems that you created yourself because you didn't know something about the language.
We all have been there. 
Maybe you are learning Javascript and you are in this process of dealing with problems you don't see happening in most programming languages.

In this post, I will show you some code snippets and for some, an embedded codepen. However, you will see `document.write` calls instead of `console.log`. This is just to allow you to see the output on the codepen's app. Otherwise, you would have to open your browser's developer tools.

Let's look at the following JS code snippet:

```javascript
console.log('Hello, my name is ', name);

var name = 'Sam';
```

{% codepen https://codepen.io/codingsam01/pen/BXNGqO default-tab=js %}

What do you think that is going to happen? 
Here, you are using a variable before declaring it and assigning a value. This kind of code, in most programming languages, would throw an error because you are trying to use something that is not known yet.
You will see the following output in the console:

```bash
Hello my name is undefined
```

There was not a single error, but you get an unexpected output.
`undefined` is the default value of any variable.

If you don't know what is going on, you start to ask yourself:

- Why didn't the code crash when I tried to use an unknown variable?

- Is there some magic that allows me to use a variable declared below? If so, why didn't I get the right variable's value and got `undefined` instead?

In the previous code example, try to replace `name` by something else:

```javascript
console.log('Hello, my name is ', somethingElse);

var name = 'Sam';
```

{% codepen https://codepen.io/codingsam01/pen/NQGJxa default-tab=js %}

You will get this:

```
ReferenceError: somethingElse is not defined
```

This error is something that any Javascript beginner would expect.
But it didn't happen in the previous example. It seems that you can use variables before they are declared.

Actually, something else happens behind the scenes to allow developers to do that. It's called *Hoisting*. Let me help you to understand one of the most tricky features of Javascript, specially for beginners. I will also show you how you can avoid it and when it can be useful.

# What is *Hoisting*?

*Hoisting* is a process that moves all the declarations to the top of their scope. This is handled by the Javascript engine before running your code.

But... What is the scope of a declaration?

In Javascript, you have function based scope, which means, any variable declared inside a function, will belong to that function's scope, no matter where in the function it happens. For instance, if you declare a variable inside a for loop, that variable will be known anywhere in the function and not just in the loop.
But, any function or variable declared outside a function, will belong to the global scope.

Only declarations are *hoisted* (moved to the top).
But, which types of declarations?

- variable declarations using the `var` keyword;

- functions using the `function` keyword;

Be careful about `var` declarations. It is really easy to look at an assignment and think that the variable's name and value will be moved to the top.

Let's look at an example:

```javascript
var a = 2;
```

In this line of code, there are two things going on, a declaration and an assignment. This line could be translated to:

```javascript
var a;
a = 2;
```

Only the declaration `var a` will be hoisted. Like what happened in the first code snippet, if you try to use the variable `a` before the assignment, it will be `undefined` and not `2`.

However, when you declare a function, you also write its body. You can't create a function with just a name and specify its behavior later on. That's why, when you declare a function (using the `function` keyword) the whole function gets hoisted. This means that, you can declare it in a line after the first call.
For instance, the following example will not throw an error:

```javascript
var message = getMessage('Sam');
console.log(message);

function getMessage (name) {
  return 'Hello my name is ' + name;
}
```

{% codepen https://codepen.io/codingsam01/pen/PoYzdgr default-tab=js %}

You will see "Hello my name is Sam" on the console. The `getMessage` function got hoisted, which means, moved to the top, by the Javascript engine before running the code.

# Let's see it in action!

Look at the following code snippet:

```javascript

var message = getMessage('Sam');

function getMessage (name) {

  var completeMessage = intro + ' ' + name;
  var intro = 'Hello my name is';
  return completeMessage;
}

console.log('Message: ', message);
```

{% codepen https://codepen.io/codingsam01/pen/JjPKaqv default-tab=js %}

The output will be "Message: undefined Sam".
Before running the code, declarations will be hoisted. Let's break down *Hoisting* and follow through the steps:

- First, collect all declarations (`var` and `function`)

![Highlighting all declarations](https://thepracticaldev.s3.amazonaws.com/i/vwbc44wrxedyiqhcr32s.png)

- Move those declarations to the top of their scope

![Moving all declarations to the top of their scope](https://thepracticaldev.s3.amazonaws.com/i/74dpwcfri9qo7y9mgshr.png)

After this process, the Javascript engine will look at your code like this:

```javascript
var message;

function getMessage (name) {
  var completeMessage;
  var intro;
  completeMessage = intro + ' ' + name;
  intro = 'Hello my name is';
  return completeMessage;
}

message = getMessage('Sam');

console.log('Message: ', message);
```

The `message` variable and `getMessage` function are global, that's why they were moved to the top of the file. The `completeMessage` and `intro` variables were moved to the top of the `getMessage` body, because they are attached to the function's scope.

The `completeMessage` variable will be `undefined Sam`, because the assignment to the variable `intro` happens one line below.

# Can you run away from it?

How many programming languages do you know that have this *Hoisting* feature? Most programming languages don't have it, which means, if you try to use a variable or a function that is not declared yet, you will get an error. For me, it makes a lot of sense. Why would you use a variable before you declare it in the first place?
I don't really know why Javascript has *Hoisting*. But, I know that [ES6 (ECMAScript version 6)](http://es6-features.org) added ways of declaring variables that are not hoisted.
ECMAScript is a standardized specification, that Javascript is based on.

If, at this point, you think that *Hoisting* was a bad idea, maybe you are not the only one and the people that work on the ES specification think like you. Maybe that's why they have created the `const` and `let` keywords, that allow you to define constants and variables, respectively. They are not hoisted.

Nowadays, a lot of Javascript developers are not using `var` anymore, because of *Hoisting* and the function based scope.
See my post on "Why don't we use var anymore?"
{% link https://dev.to/codingsam/why-don-t-we-use-var-anymore-c71 %}

In the following example:

```javascript
const message = getMessage('Sam');
function getMessage (name) {
  const completeMessage = intro + ' ' + name;
  const intro = 'Hello my name is';
  return completeMessage;
}

console.log('Message: ', message);
```

{% codepen https://codepen.io/codingsam01/pen/wvwWYwB default-tab=js %}

You will get an error inside the `getMessage` function, because you are trying to use the constant `intro` before you declare it and assign it a value.
Calling `getMessage` before defining it does not throw an error because, remember, functions are hoisted. But there is also a solution to create non hoisted ones. Just use *arrow functions*.

```javascript
const getMessage = (name) => {
  return 'Hello my name is ' + name;
}
```

They are not hoisted because they don't have a name (you are not using the `function` keyword). When you create an arrow function, you are creating an anonymous function. If you want to keep a reference to it, you have to assign that anonymous function to a constant or a variable.

# Is it all bad?

So far, I have shown you what *Hoisting* is and how you can avoid it. However, I think that it is not all that bad. There is one good use case for this feature. 

Let's say you have a `location.js` file, that exports a function that any developer can use to get the user's location. Before getting the location, you need to ask permission to get that data. Your file would look something like this:

```javascript
export const getUserLocation () {
  const userAllowedToGetLocation = askUserPermission();
  if (userAllowedToGetLocation) {
    return userLocation();
  }
  else {
    throw new Error('User refused to provide location');
  }
}

function askUserPermission () {
  // Logic to ask user permission to get his/her location
}

function userLocation () {
  // Logic to get the user's location
}
```

The exported function is a constant with an arrow function as its value. But, that function uses two other functions, which are defined after the exported `getUserLocation`.
You can do this because, remember, functions in Javascript are hoisted, but not arrow functions. If these auxiliary functions were arrow functions, you would have to put them before the exported one. This is a simple example but sometimes, you can have more than two auxiliary functions. Other developers that need to work on that file would have to scroll until they find what is being exported.

If you put all the auxiliary functions on the bottom of the file, you make it easier to read, because other developers will see the main logic as soon as they open the file, instead of having to scroll through a lot of functions.

I use this pattern a lot... But you might disagree ;)

# Conclusion

*Hoisting* is a feature that can be tricky to a lot of developers. Fortunately, we have ways to avoid that process of moving all the declarations to the top of their scope. But, you can put this feature to good use. When you have a file that exports something, you can move all auxiliary functions to the bottom and make your code easier to read.

Do you like *Hoisting*? Do you think that it is useful? Do you know other ways of taking advantage of it? Let me know what you think in the comments!

Happy coding! :)

- [Coding Sam](https://medium.com/u/58cf94a36c97) @ Medium

- [codingsam @ Twitter](https://twitter.com/codingsam01)