JavaScript ES6: A crash course on modern JS

Sara
8 min readApr 24, 2022

--

Summary — updated April 2022

Babel

One of the biggest changes from ES5 is that ES7 JavaScript is not able to be compiled directly in browsers. We need to use a transpiler called Babel.js to produce compatible JavaScript that the older browsers can read.

Babel allows you to use ES6 features and syntax in your project and then translates it to ES5 so that you can use it in production.

Read: How to: use Babel once your project is built.

The Most Important ES2016 Updates

The most important ES2016 updates

ES6 — Array.prototype.includes( )

The .includes( ) method makes it easier for you to check if particular values are stored in an array. In the past, JavaScript developers had to use indexOf and create a new function. But .include( ) will return true if an array includes an element and false if it does not. Take a look below to see it in action.

let array = [1,3,5,9];
console.log(array.includes(4));
// true
console.log(array.includes(5));
// false

ES6 — The exponential operator

The exponential operator simplifies the way we do math in JavaScript.

In the past, we had to use loop, recursive functions, or Math.pow( ), which could get pretty messy with each concatenation.

console.log(2**2);
console.log(2**3);

ES6 — latest update: .map

Before ES6, JavaScript developers used objects to map keys to values, but using an object as a map has some restrictions:

  • There’s no dependable way to iterate over keys
  • The keys() method converts fields to strings, which creates key collision
  • There’s no simple way to add new keys and new values

These issues were addressed in the ES6 release when the Map collection type was introduced. It can hold key-value pairs of any type and can remember key insertion order. Any value (objects and primitives) can be used as a key or a value.

JavaScript Map creates a new array, which contains the results from the iteration over the elements of the array and calls the provided function once for each element in order.

To create a new Map, follow this syntax:

let map = new Map([iterable]);
JavaScript map syntax

Description:
· array: the array on which the specific function is called
· map: the method called for the array with the required parameters
· function(currentValue, index, arr): the function with its parameters, which is required to run for each element in the array
· currentValue: the value of the current element
· index:
the index of the current element
· arr: the array object on which the map() is called
· thisValue: the value used as the function’s this value when it’s executed

//creating an array
let an_array = [5, 3, 1, 4, 2]
//map calls a function with “item” as parameter
//map will pass each element of an_array as “item” in this function
//the function will triple each element passed and return it as the return value
result = an_array.map(function(item) {
return item*3;
});
//new list will print with the tripled values
console.log(result);

Return a value mapped to a specific key

userRoles.get(robin); // actress

Return a boolean value showing whether a specified key exists

userRoles.has(emma); // false
userRoles.has(ruby); // true

Return the number of entries in the map

console.log(userRoles.size); // 4

Return a new iterator object that includes the value of each element

for (let role of userRoles.values()) {
console.log(role);
}
// director
// producer
// writer
// actress

Remove specified elements from map object

userRoles.delete(ruby);

Remove all elements in map object

userRoles.clear();
console.log(userRoles.size); // 0

ES6 — Advanced map concepts

JavaScript Map is a valuable collection type that makes programming with JavaScript cleaner and more efficient.
Some recommended concepts to cover next are:

  • Metaprogramming
  • Prototypal inheritance
  • Implementing constructors
  • Literals

ES6 — latest update: set

A JavaScript set is a collection of unique elements that can be traversed in the same order in which they were inserted.

A set can store primitive or object values​.

var example_set = new Set([“apple”,”bannana”,”mango”,”kiwi”]);
console.log(example_set)

There are various methods and properties implemented in the Set class.
A few of them are described below.

  • Set.prototype.size returns the number of elements in the set.

// print size of the set
console.log(fruits.size)

  • Set.prototype.add(val) adds the new element val at the end of the Set object.

// add “orange” to fruits.
fruits.add(“orange”)
console.log(fruits.values())

  • Set.prototype.delete(val) deletes the element val from the Set object.

// remove “kiwi” from fruits.
fruits.delete(“kiwi”)
console.log(fruits.values())

  • Set.prototype.clear() removes all the elements from the set.

// clear the set
fruits.clear()
console.log(fruits.values())

  • Set.prototype.has(val) returns true if val is present in the Set object.

// check if fruits contains “apple”
console.log(fruits.has(“apple”))

  • Set.prototype.values() returns all the values from the Set in the same insertion order.

console.log(fruits.values())

ES6 — latest update: generators

From its name, a generator is a function that allows you to generate one or more values by exiting and re-entering the execution procedure whilst saving its state (context) across multiple calls. To put it in simpler words, a generator is similar to normal functions, but has the ability to continue execution on demand at the point at which it was previously terminated, simply by saving its previous state.

There are some syntactic differences between a normal function and a generator:

// Normal Function
function normalFunction(params) {
// your logic goes here
return value;
}
/* --------------------------------- */// Generator Function
function* generatorFunction(params) {
// your logic
yield value1;
// your logic
yield value2;
/*
.
.
.
*/
// your logic
yield valueN;
}

The first noticeable difference in syntax is that a generator is declared using the function* keyword instead of function. Also, notice how we use the return keyword in a normal function, while we use the yield keyword in a generator function instead, respectively. The yield keyword inside the generator allows us to 'return' a value, terminate execution, save the state (context) of the current lexical scope and waits for the next invocation to resume execution at the last termination point.

note: In a normal function, you can only execute the return keyword once, which will return a value and terminate the function completely. In a generator, you can use the yield keyword multiple times as much as you want to 'return' values on consecutive calls. You can also use the return keyword inside a generator, but leave this discussion for a different day.

Invocation

function normalFunction() {
console.log('I have been invoked');
}
// invocation
normalFunction();
----I have been invoked

In general, you can invoke a normal function by typing the function’s signature followed by a pair of parentheses ().

Now let’s try to use the same procedure to invoke a generator:

function* generatorFunction() {
console.log('I have been invoked');
yield 'first value';
console.log('resuming execution');
yield 'second value';
}
// does this invoke the generator?
generatorFunction();

In general, you can invoke a normal function by typing the function’s signature followed by a pair of parentheses ()but it’s not onGeneratorObject case.

The first and the most important method is called next(), which, from its name, yields the next value from the defined generator. Now lets modify our previous code to actually yield our values:

function* generatorFunction() {
console.log('I have been invoked');
yield 'first value';
console.log('resuming execution');
yield 'second value';
}
// store the Generator Object in a variable
let foo = generatorFunction();
// execute until we yield the first value
console.log(foo.next());
// resume execution until we yield the second value
console.log(foo.next());
// execute until the function ends
console.log(foo.next());
----I have been invoked
{ value: 'first value', done: false }
resuming execution
{ value: 'second value', done: false }
{ value: undefined, done: true }

When calling the first foo.next() method, the generator began to execute until it hit the first yield keyword and stops the execution. This is reflected in the first two lines of the output. Notice how the foo.next() returned an Object instead of the actual yielded value. This Object should always contain the following properties:

  • ‘value’: which holds the current yielded value from the generator.
  • ‘done’: a boolean flag which indicates whether the generator execution has reached the end or not.

ES6 — latest update: Block-Scoped Let and Const

ES6 introduced the keywords let and const that enable us to declare variables much easier. Previously, variables declared with var are function scoped, so if we declare them inside a for loop they will be available outside of the loop.

Variables declared with let and const are block-scoped, which means they are only accessible within the block where they were declared. So, if we declare a variable with let, it does not change its value in the outer scope. Const is similar, but the value of variables declared with this keyword cannot change through reassignment.

// using `var`
var y = “global”;

if (y === “global”) {
var y= “block-scoped”;

console.log(y);
// expected output: block-scoped
}

console.log(y);
// expected output: block-scoped

// using `let`
let x = “global”;

if (x === “global”) {
let x = “block-scoped”;

console.log(x);
// expected output: block-scoped
}

console.log(x);
// expected output: global

There is no hard-and-fast rule about when to use which variables. Here are two different opinions from popular JavaScript developers on how to use these three variables.

From Mathias Bynes: Use const by default and let if rebinding is needed. var should never be used in ES6.

From Kyle Simpson: Use var for top-level variables that are shared across many scopes. Use let for smaller scopes.

ES6 — latest update: Arrow functions

ES6 introduced arrows (=>) as a shorthand way to declare functions. This update has three notable advantages:

  • You no longer have to use .bind( ) method
  • Code is much cleaner and less verbose
  • You can skip the explicit return

var greeting = (name) => {
console.log(`hello ${name}`);
}

There are some cases where you will want to avoid using arrow functions. You need to be careful when using it alongside the this keyword. Now, when you use the arrow function, the this keyword is inherited from the parent scope.

ES6 — latest update: Classes

The updates to classes in ES6 do not introduce a new OO inheritance model. Instead, these classes are “syntactical sugar” to support prototype inheritance. This update is useful because it simplified your code without changing the basic model of JavaScript. It’s essentially a nicer, cleaner way of doing inheritance. You can create a class in two ways:

  • class declaration
  • class expression

You will need the method constructor to create a class.

class Person {
constructor(name, age){
this.name = name;
this.age = age;
}
greet(){
console.log(`My name is ${this.name} and I am ${this.age} years old` );
} // no commas in between methods
}

const sarah = new Person(“Sarah”,35);

sarah.greet();

ES6 — latest update: Template Literals

ES6 implemented the useful feature of template strings, now called template literals. This allows you to easily implement variables with a very simple syntax (${ }) and embed expressions.

It’s particularly useful for constructing API requests and nesting templates.

  • The template literal syntax is enclosed in backticks.
  • The syntax placeholders in template literals use ${expression}

let name = “Sarah”;
const greeting = `Hello my name is ${name}`;
console.log(greeting);

ES6 — Other updates with ES6

  • Additional String Methods
  • Destructuring
  • Array Improvements
  • Symbols
  • Promises
  • Default function arguments i.e. default parameters and default values
  • Generator
  • Proxies
  • Object literal updates
  • Sets, WeakSets, Maps, and WeakMaps

Last updated: April 2022

--

--