Destructuring Tweets - Episode 2 - Hoisting
Tags: snippet, javascript, destructuring, hoisting
Published: 2021-01-10 09:57:16

---
title: Destructuring Tweets - Episode 2 - Hoisting
published: true
description: I pick a more or less random snippet from Twitter and analyze it in depth in this series. It shall help me, and you understand the trickery behind it. This episode features the concept of hoisting and how it varies between `let` and `var`.
tags: snippet, javascript, destructuring, hoisting
//cover_image: https://direct_url_to_image.jpg
---

Hey, welcome to my series about destructuring one of those often shared snippet quizzes on Twitter. Welcome to this week's episode!
#Snippet of the Week
This week's [snippet](https://twitter.com/DenverCoder1/status/1347232881656135684) is from [Jonah Lawrence](https://twitter.com/DenverCoder1):
```javascript
function fooBar() {
  try {
    console.log(foo);
  } catch (error) {
    console.log(error.name);
  }
  try {
    console.log(bar);
  } catch (error) {
    console.log(error);
  }
  var foo = 'hello';
  let bar = 'world';
}

fooBar();
```
In this snippet, they start with two `try`/`catch` blocks. These catch errors and allow us to act upon them, like adding an entry to our log-database or informing the user.
Both of them either print a variable or the name of the thrown object in case of error. Note that both of the trying-to-be-printed-variables are yet to be declared. That missing is the core trickery here.
After the two `try`/`catch` blocks, we have the actual declaration of the variables. The first one being initialized via `var`, the second one with `let`. 
#The Output
So, what will the output be if I run the given function? Surprisingly enough, it's `undefined` and a `ReferenceError`. To be a little more precise, we print the variable `foo` (which is `undefined` at this point), but not the variable `bar`. Latter is recognized as not declared at all, hence `ReferenceError`, which semantically means "You did not declare this variable".
#Analysis
First things first, why is `foo` `undefined`? Shouldn't it be `hello`? No, because of a concept called hoisting. Javascript engines move the (non-lexical) variable declarations to the top of the scope! What does this mean for our example? This shows how `foo` gets processed:
```javascript
function fooBar() {
  var foo; // undefined
  try {
    console.log(foo);
  } catch (error) {
    console.log(error.name);
  }
  foo = 'hello';
}
```
An uninitialized variable is always just `undefined`. The variable is declared; hence it can be printed but has not yet an assigned value.
The second and more significant question is why the behavior is not the same for `let` and `var`. Easy answer: `let` is a lexical variable, while `var` is not. ES6 introduced the difference for precisely this type of errors. The interpreter is more prone to detect hoisting mistakes that way.
A lexical variable behaves like most of us would intuitively expect it to be. One can not access it before it gets initialized. Such are placed in the Temporal Dead Zone (TDZ). Notably, lexical variables, so practically `let` and `const`, do not get hoisted.
One addition, one might instantly think that this snippet wants to trick you with scope differences. That's not the case here! The block-scope equals the function-scope.
# Snippet Summary
- **Trickery**: Difference in the hoisting of lexical and non-lexical variables
- **Key Learning**: Lexical variables do not get hosted, thus can not be accessed before being initialized
- **Further reading**:
    - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init
    - https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/
    - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz
    - https://developer.mozilla.org/en-US/docs/Glossary/Hoisting