Why should you learn Modern JavaScript — ES6

Al Mahamud Murad
9 min readMay 6, 2021

Some ES6 features

JavaScript ES6 brings new syntax and new awesome features to make your code more modern and more readable. It allows you to write less code and do more. ES6 introduces us to many great features.

1. Default Parameters in ES6

Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed.

function multiply(x, y= 1) {
return x* y;
}
console.log(multiply(9, 2));
// expected output: 18
console.log(multiply(9));
// expected output: 9

2. Template Literals in ES6

Template Strings use back-ticks (``) rather than the single or double quotes we're used to with regular strings. A template string could thus be written as follows:

var greeting = `Hello World!`;

So far, Template Strings haven’t given us anything more than normal strings do. Let’s change that.

String Substitution

One of their first real benefits is string substitution. Substitution allows us to take any valid JavaScript expression (including saying, the addition of variables) and inside a Template Literal, the result will be output as part of the same string.

Template Strings can contain placeholders for string substitution using the ${ } syntax, as demonstrated below:

// Simple string substitution
var name = "Brendan";
console.log(`Yo, ${name}!`);
// => "Yo, Brendan!"

As all string substitutions in Template Strings are JavaScript expressions, we can substitute a lot more than variable names. For example, below we can use expression interpolation to embed for some readable inline math:

var a = 10;
var b = 10;
console.log(`JavaScript first appeared ${a+b} years ago. Wow!`);
//=> JavaScript first appeared 20 years ago. Wow!console.log(`The number of JS MVC frameworks is ${2 * (a + b)} and not ${10 * (a + b)}.`);
//=> The number of JS frameworks is 40 and not 200.

They are also very useful for functions inside expressions:

function fn() { return "I am a result. Rarr"; }
console.log(`foo ${fn()} bar`);
//=> foo I am a result. Rarr bar.

The ${} works fine with any kind of expression, including member expressions and method calls:

var user = {name: 'Caitlin Potter'};
console.log(`Thanks for getting this into V8, ${user.name.toUpperCase()}.`);
// => "Thanks for getting this into V8, CAITLIN POTTER";// And another example
var thing = 'template strings';
console.log(`Say hello to ${thing}.`);
// => Say hello to template strings

If you require backticks inside of your string, it can be escaped using the backslash character \ as follows:

var greeting = `\`Yo\` World!`;

3. Multi-line Strings in ES6

Multiline strings in JavaScript have required hacky workarounds for some time. Current solutions for them require that strings either exist on a single line or be split into multiline strings using a \ (backslash) before each new line. For example:

var greeting = "Yo \
World";

Whilst this should work fine in most modern JavaScript engines, the behavior itself is still a bit of a hack. One can also use string concatenation to fake multiline support, but this equally leaves something to be desired:

var greeting = "Yo " +
"World";

Template Strings significantly simplify multiline strings. Simply include newlines where they are needed and BOOM. Here’s an example:

Any whitespace inside of the backtick syntax will also be considered part of the string.

console.log(`string text line 1
string text line 2`);

4. Destructuring Assignment in ES6

The two most used data structures in JavaScript are Object and Array.

  • Objects allow us to create a single entity that stores data items by key.
  • Arrays allow us to gather data items into an ordered list.

Although, when we pass those to a function, it may need not an object/array as a whole. It may need individual pieces.

Destructuring assignment is a special syntax that allows us to “unpack” arrays or objects into a bunch of variables, as sometimes that’s more convenient.

Destructuring also works great with complex functions that have a lot of parameters, default values, and so on. Soon we’ll see that.

Array destructuring

Here’s an example of how an array is destructured into variables:

// we have an array with the name and surname
let arr = ["John", "Smith"]
// destructuring assignment
// sets firstName = arr[0]
// and surname = arr[1]
let [firstName, surname] = arr;
alert(firstName); // John
alert(surname); // Smith

Now we can work with variables instead of array members.

It looks great when combined with split or other array-returning methods:

let [firstName, surname] = "John Smith".split(' ');
alert(firstName); // John
alert(surname); // Smith

As you can see, the syntax is simple. There are several peculiar details though. Let’s see more examples, to better understand it.

5. Enhanced Object Literals in ES6

The ability to create JavaScript objects using literal notation is powerful. New features introduced from ES2015 (ES6) make object handling even easier in all modern browsers (not IE) and Node.js.

Creating objects in some languages can be expensive in terms of development time and processing power when a class must be declared before anything can be achieved. In JavaScript, it’s easy to create objects on the fly. For example:

// ES5-compatible code
var myObject = {
prop1: 'hello',
prop2: 'world',
output: function() {
console.log(this.prop1 + ' ' + this.prop2);
}
};
myObject.output(); // hello world

Single-use objects are used extensively. Examples include configuration settings, module definitions, method parameters, return values from functions, etc. ES2015 (ES6) added a range of features to enhance object literals.

6. Arrow Functions in ES6

Arrow functions were introduced in ES6.

Arrow functions allow us to write shorter function syntax:

With Arrow Function:

hello = () => {
return “Hello World!”;
}

It gets shorter! If the function has only one statement, and the statement returns a value, you can remove the brackets and the return keyword:

Arrow Functions Return Value by Default:

hello = () => “Hello World!”;

Note: This works only if the function has only one statement.

If you have parameters, you pass them inside the parentheses:

Arrow Function With Parameters:

hello = (val) => “Hello “ + val;

In fact, if you have only one parameter, you can skip the parentheses as well:

Arrow Function Without Parentheses:

hello = val => “Hello “ + val;

7. Promises in ES6

A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.

A Promise is in one of these states:

  • pending: initial state, neither fulfilled nor rejected.
  • fulfilled: meaning that the operation was completed successfully.
  • rejected: meaning that the operation failed.

A pending promise can either be fulfilled with a value or rejected with a reason (error). When either of these options happens, the associated handlers queued up by a promise’s then method are called. If the promise has already been fulfilled or rejected when a corresponding handler is attached, the handler will be called, so there is no race condition between an asynchronous operation completing and its handlers being attached.

8. Block-Scoped Constructs Let and Const

Let

let is now preferred for variable declaration. It's no surprise as it comes as an improvement to var declarations. It also solves the problem var that we just covered. Let's consider why this is so.

let is block scoped

A block is a chunk of code bounded by {}. A block lives in curly braces. Anything within curly braces is a block.

So a variable declared in a block let is only available for use within that block. Let me explain this with an example:

let greeting = "say Hi";
let times = 4;
if (times > 3) {
let hello = "say Hello instead";
console.log(hello);// "say Hello instead"
}
console.log(hello) // hello is not defined

We see that using hello outside its block (the curly braces where it was defined) returns an error. This is because let variables are block-scoped.

let can be updated but not re-declared.

Just like, a variable declared with let can be updated within its scope. Unlike, a let variable cannot be re-declared within its scope. So while this will work:

let greeting = "say Hi";
greeting = "say Hello instead";

this will return an error:

let greeting = "say Hi";
let greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared

However, if the same variable is defined in different scopes, there will be no error:

let greeting = "say Hi";
if (true) {
let greeting = "say Hello instead";
console.log(greeting); // "say Hello instead"
}
console.log(greeting); // "say Hi"

Why is there no error? This is because both instances are treated as different variables since they have different scopes.

This fact makes let a better choice than var. When using let, you don't have to bother if you have used a name for a variable before as a variable exists only within its scope.

Also, since a variable cannot be declared more than once within scope, then the problem discussed earlier that occurs with var does not happen.

Hoisting of let

Just like var, let declarations are hoisted to the top. Unlike var which is initialized as undefined, the let keyword is not initialized. So if you try to use a let variable before the declaration, you'll get a Reference Error.

Const

Variables are declared with the const maintain constant values. const declarations share some similarities with let declarations.

const declarations are block-scoped

Like let declarations, const declarations can only be accessed within the block they were declared.

const cannot be updated or re-declared

This means that the value of a variable declared with const remains the same within its scope. It cannot be updated or re-declared. So if we declare a variable with const, we can neither do this:

const greeting = "say Hi";
greeting = "say Hello instead";// error: Assignment to constant variable.

nor this:

const greeting = "say Hi";
const greeting = "say Hello instead";// error: Identifier 'greeting' has already been declared

Every const declaration, therefore, must be initialized at the time of declaration.

This behavior is somehow different when it comes to objects declared with const. While a const object cannot be updated, the properties of this objects can be updated. Therefore, if we declare a const object as this:

const greeting = {
message: "say Hi",
times: 4
}

while we cannot do this:

greeting = {
words: "Hello",
number: "five"
} // error: Assignment to constant variable.

we can do this:

greeting.message = "say Hello instead";

This will update the value of greeting.message without returning errors.

Hoisting of const

Just like let, const declarations are hoisted to the top but are not initialized.

So just in case you missed the differences, here they are:

  • var declarations are globally scoped or function scoped while let and const are block scoped.
  • var variables can be updated and re-declared within its scope; let variables can be updated but not re-declared; const variables can neither be updated nor re-declared.
  • They are all hoisted to the top of their scope. But while var variables are initialized with undefined, let and const variables are not initialized.
  • While var and let can be declared without being initialized, const must be initialized during declaration.

9. Classes in ES6

ECMAScript 2015, also known as ES6, introduced JavaScript Classes.

JavaScript Classes are templates for JavaScript Objects.

JavaScript Class Syntax

Use the keyword class to create a class.

Always add a method named constructor():

Syntax

class ClassName {
constructor() { … }
}

Example

class Car {
constructor(name, year) {
this.name = name;
this.year = year;
}
}

The example above creates a class named “Car”.

The class has two initial properties: “name” and “year”.

A JavaScript class is not an object.

It is a template for JavaScript objects.

Using a Class

When you have a class, you can use the class to create objects:

Example

let myCar1 = new Car(“Ford”, 2014);
let myCar2 = new Car(“Audi”, 2019);

The example above uses the Car class to create two Car objects.

The constructor method is called automatically when a new object is created.

The Constructor Method

The constructor method is special:

  • It has to have the exact name “constructor”
  • It is executed automatically when a new object is created
  • It is used to initialize object properties

If you do not define a constructor method, JavaScript will add an empty constructor method.

Class Methods

Class methods are created with the same syntax as object methods.

Use the keyword class to create a class.

Always add a constructor() method.

Then add any number of methods.

Syntax

class ClassName {
constructor() { … }
method_1() { … }
method_2() { … }
method_3() { … }
}

Create a Class method named “age”, that returns the Car age:

Example

class Car {
constructor(name, year) {
this.name = name;
this.year = year;
}
age() {
let date = new Date();
return date.getFullYear() — this.year;
}
}
let myCar = new Car(“Ford”, 2014);
document.getElementById(“demo”).innerHTML =
“My car is “ + myCar.age() + “ years old.”;

You can send parameters to Class methods:

Example

class Car {
constructor(name, year) {
this.name = name;
this.year = year;
}
age(x) {
return x — this.year;
}
}
let date = new Date();
let year = date.getFullYear();
let myCar = new Car(“Ford”, 2014);
document.getElementById(“demo”).innerHTML=
“My car is “ + myCar.age(year) + “ years old.”;

10. Modules in ES6

Modules in ES6 is an essential concept. Although it is not available everywhere, we can use it and transpile into ES5 code. Transpilation is the process of converting the code from one language into its equivalent language. The ES6 module transpiler tool is responsible for taking the ES6 module and converts it into a compatible code of ES5 in the AMD (Asynchronous module definition is a specification for the JavaScript programming language) or in the CommonJS style.

We can use Gulp, Babel, Grunt, or other transpilers for compiling the modules during the build process. The variables and functions in a module are not available for use unless the file exports them.

--

--