Lesson 6: ES6+

Michelle Colón
The Road to React
Published in
11 min readJun 14, 2018

This is kind of a long post, this lesson covered a lot!

In order to begin my journey down the road of ES6 and beyond, I first need to understand Transpiling and Polyfilling.

Screenshot from Cassidy Williams’ Udemy Course

Both of these techniques serve the same purpose: you write your code, the code uses some modern features that are not yet implemented in your target environment, and they aim to fill the gaps. They do this, however, using different techniques.

  • A Polyfill will try to emulate certain APIs so you can use them as if they were already implemented. This is also known as shimming.
  • A Transpiler will transform your code and replace the respective code section with other code, which can already be executed.

You use a polyfill if your target browser hasn’t yet implemented the latest feature you want to use. Here’s an example of a polyfill library, if you want to explore!

Transpilers are also known as source-to-source compilers. In other words, they are tools that read source code written in one language and produce the equivalent code in another language; they let you use language features that the target environment doesn’t support yet (Babel is an example of one such transpiler).

These two concepts are similar and serve the same purpose- they just go about it in different ways.

ES6 also introduces new types of variable declarations: let and const. You might be wondering ‘Why do we need all these variable declarations?’ Well, I blame hoisting! Hoisting is when the JavaScript interpreter moves all variable and function declarations to the top of the current scope. This is usually not a really bad thing, but can cause bugs in the long run.

Example from Cassidy Williams’ Udemy Course done in the console

Cassidy explains hoisting in an awesome way. Here’s my best shot at illustrating what it is. Take a look at the code to the left. In this image, the console.log yields what we expect: 1 2.

NB: This function is called an ‘immediately invoked function’ because it is wrapped in parentheses. Immediately invoked functions do not require that you name them, they can be anonymous.

Example from Cassidy Williams’ Udemy Course done in the console

In this example, notice that we moved the console.log up one line and the result is 1 undefined. Why? Because the log takes place before b is declared. But also notice, that we did not get an error. That is because, technically, this JS is written just fine. But that’s not what we want, is it? We need to know when we have an error!

Example from Cassidy Williams’ Udemy Course done in the console

Here, if you notice, we’ve got some hoisting going on- that is, we’ve moved the declarations to the top, while the assignments stay the same. We are still susceptible to the same bug as the example before this one and that’s where let and const come in (this will make more sense, coming up!).

There is one other reason for let and const to exist, and that reason is block scoping. A block scope is a scope defined by anything within curly braces {}. Below is an example containing block scope:

Example from Cassidy Williams’ Udemy Course done in the console

The first console.log prints 20 and the second console.log prints 10. The reason for this is that the x in the scope containing let is limited to the scope of that block. Meanwhile, var x has the scope of the entire block. Both let and const are block scoped, meaning that their values are limited to the block in which they are declared.

Example from Cassidy Williams’ Udemy Course done in the console

Now, let’s take the above example and make both declarations into var- notice what it prints. As I understand it, it prints 20 twice because the var x = 20 overwrites the initial variable declaration (namely, var x = 10;).

Example from Cassidy Williams’ Udemy Course done in the console

Bear with me- let’s look at the same example again. This time, we changed all the var to let and it prints 20 then 10 like we saw before. The reason for this is that each x now pertains to its own scope.

Example from Cassidy Williams’ Udemy Course done in the console

Okay, okay, last one with this example :) As you can see, we finally got an error! When we make the outer variable a let and in the inner variable a var, we get a syntax error. This error happens because the let defines a variable that is to be used in the entire block, and redeclarations are not allowed within this block. The var has the scope of the whole function. Meanwhile, let limits the scope to a specific block and it can’t be redeclared within the same block.

So- back to the matter at hand! What is the difference between let and const? The main difference is that const (which stands for constant) variables are meant to be for constants and cannot be reassigned. Also, some information I’ve found points to only using let in loop counters. Otherwise, they are pretty similar. With both const and let, a variable can only be declared once in a given scope.

Example from Cassidy Williams’ Udemy Course done in the console

Both methods of declaration were made so that we could get more explicit errors (versus none, as we saw above) and so that variables could be more specific to scopes. Although var is now considered the “weakest” of the variable declarations because of its lack of strictness, it is still our best option for global variables because var is global by default. Meanwhile, let and const are local by default.

Now, onto a new concept: default values! Default values are those values that we put into default parameters.

[Default values give] the ability to have your functions initialize parameters with default values even if the function call doesn’t include them. — CSS Tricks

Example from Cassidy Williams’ Udemy Course done in the console

Here’s what default values look like before ES6 and after writing it with ES6. One of the reasons we write it this new way is because we needed a way to handle when a parameter was null or 0 (which evaluates as falsy).

NB: Default parameters can be a value, an expression, or a function, like this: function anotherExample(x = 3, y = 8 * x, z = example(x)){}

Onward to destructuring! Destructuring is an expression that allows us to pull data from objects and arrays and put them into their own variable. It allows us to extract properties (for an object), or items (in an array), multiple at a time.

Example from Cassidy Williams’ Udemy Course done in the console

Let’s look at this person object, for example. In order to access the first name, we can type let first = person.first and then call first. But, if we want to do the same for last, city, and employer, it can get cumbersome and repetitive- especially if you have a larger object. This is where destructuring comes in handy. Instead of going through and typing let last = person.last and then calling last, and so on, we can structure our code like this:

Example from Cassidy Williams’ Udemy Course done in the console

Here, we can call first, last, city, or employer and it’s more efficient.

Side note! When we destructure, we can also have default values! For example, we could take the code from the above screenshot and put in a default value and it would look like this: let {first, last, city, employer, friend = "Jack Sparrow"} = person. Here, Jack Sparrow will always be a friend of person.

Okay, so, I’m about to hit you with a bunch of examples involving destructuring. Ready?

In destructuring, we have the option to change variable names. Below you will see that we give first the variable name of firstName, and so on. That way, we can call firstName and get the same result, if we need to.

Example from Cassidy Williams’ Udemy Course done in the console

Repeated assignments and assignments to unnamed objects are also allowed. I’m not super clear as to when I would want to do this, but I thought I’d include it, for reference. (If anyone knows why/when this would be used, I’d welcome the knowledge).

Example from Cassidy Williams’ Udemy Course done in the console

Destructuring also works with arrays. Take a look, and I will explain.

Example from Cassidy Williams’ Udemy Course done in the console

The way I think about this is that the x corresponds to numbers 1, 2, and 3, which are in an array; it also corresponds to the array containing a, b, and c. So, the destructuring is happening when x takes the a value, for example, and pairs it with the number 1, and so on. In my mind, I see it as x taking the structure of both arrays and breaking it into individual pieces.

Swapping variables is another feature of destructuring. Check it out- this is how we would’ve begun the code, pre-ES6:

Example from Cassidy Williams’ Udemy Course done in the console

If we wanted to swap the variables, we’d have to assign hello to a temporary third variable and then replace the value of y with world, and move assignments around until we got the desired end result. An easier way to do that would be to stick the values in an array and flip them, like this:

Example from Cassidy Williams’ Udemy Course done in the console

How cool is that? It’s like magic! And there is no temporary variable needed :)

*phew*

That’s all for destructuring- let’s move onto literals. In ES6, there are two types of literals: object literals and template literals.

Screenshot from Cassidy Williams’ Udemy Course

Object literals provide a shorthand syntax for initializing properties for variables and defining functions. Take the following, for example.

Screenshot from Cassidy Williams’ Udemy Course

If we wanted to have an object called z that held the properties for x and y, we would do this, pre-ES6:

Screenshot from Cassidy Williams’ Udemy Course

Now, with ES6 and object literals, we can write the following, and it yields the same result.

Screenshot from Cassidy Williams’ Udemy Course

The same also goes for defining functions. The way we’re used to seeing it is:

Screenshot from Cassidy Williams’ Udemy Course

Now, in ES6, we can do this:

Screenshot from Cassidy Williams’ Udemy Course

Here, we are cutting out the whole function definition and naming the function only with the parentheses( x() and y()). These are called concise methods (these are used a lot in React!). Object literals provide a shorthand syntax that initialize properties from variables and they define these concise functions.

Template literals are not similar to object literals (they just have a similar name)- you might also know them as string literals. They have the type “string.”

Before, if you wanted to include a variable in a string, you might write something like this:

Screenshot from Cassidy Williams’ Udemy Course

Now, with template literals, you can do it like this:

Screenshot from Cassidy Williams’ Udemy Course

Notice that a template literal is defined with back-ticks and variables are included with the dollar sign and curly braces. Again, it will produce the exact same result as the pre-ES6 code. That dollar sign and curly brace syntax is called interpolation and doesn’t have to just be a variable- it can also be an expression or a function.

We can also nest template literals. Here is an example that I’ll walk through. This was done in the console, so there are no line numbers, but I think it will be relatively easy to follow.

Example from Cassidy Williams’ Udemy Course done in the console
  • First, the capitalize function is going to return a string that will be converted to uppercase.
  • Next, we define the you variable as class
  • Then, we create a template literal in t (don’t forget to start and end with the back-tick!) In there, we insert an expression and provide the function with a string (i.e. big). After that, we’ll add in another expression that contains the capitalize function which, itself, contains another template literal with a string (i.e. you) and then we’re done with all the nesting!
  • When we console.log the variable t, we get capital letters in the appropriate places.
  • One thing to note is that line breaks are evaluated in template literals. That said, we do not need a \n for a new line in between strings.

And lastly, my favorite- arrow functions!

Before , functions were written like this, which is still totally valid:

Screenshot from Cassidy Williams’ Udemy Course

But now, with arrow functions, we can write the same function like this:

Screenshot from Cassidy Williams’ Udemy Course

With this new syntax, please note the following:

  • The first bit (var add) is declaring a variable and assigning an anonymous function to it ((x,y))- so it’s saying that the variable add is actually a function.
  • The second part (after the arrow) is the body of what’s being returned.

We will, of course, have times when we are returning something with more logic in it, in which case we would write the arrow function as follows, and put all our logic between the curly braces.

Screenshot from Cassidy Williams’ Udemy Course

Here are the key things to remember about arrow functions!

Screenshot from Cassidy Williams’ Udemy Course

Allow me to explain the third point on there. The this binding is lexical (a.k.a. static) instead of dynamic. To explain that a bit further, I’ll give one last example (I promise!). In this example, there is an object with a function in it that has an event listener.

Screenshot from Cassidy Williams’ Udemy Course

With this way of writing the code, if you wanted to have access to the object via this, you’d have to make a new variable that points to this (i.e. var self = this;) outside of the callback in order to use it (self.doSomething(…)). In this case, since we have the this inside the anonymous function, this is referring to the event inside the small scope rather than the larger scope of the makeRequest function in the control object.

However, with arrow functions, the context does not change. We can simply use the this keyword. this does not change in a given function, it stays the same (a.k.a. it is static).

Screenshot from Cassidy Williams’ Udemy Course

Man, that was a long post!

Next up is REACT!!! Can’t wait to finally start diving in!

Photo by Archaique Chang on Unsplash

--

--