The Modern JavaScript

Tanveer
5 min readMar 25, 2021

ECMAScript 6, also known as ECMAScript 2015, brought significant changes to the JavaScript language. It introduces several new features such as arrow functions, block-scoped variables, a new loop for iterating over arrays and objects, a Logical Assignment Operator, template literals, and many other enhancements to make JavaScript programming easier and more fun. Implementation of new features in major JavaScript engines is underway now. let's discuss some of the best ES6 features in brief that we can use in our everyday JavaScript coding.

Let & Const

The scope of a variable declared using let is only the block it is in and whereas with const, you declare a read-only reference to a value. Block-scoped binding constructs. let is the new var. const is single-assignment.

function foo() {
{
let x;
{
const x = "sneaky";
x = "foo"; // error, const is single-assignment
}
let x = "inner"; // error, already declared in block
}
}

Template Literals

Template literals provide a clean way to create strings and perform string interpolation avoiding injection attacks or constructing higher-level data structures from string contents.

const name = 'Tanveer';
const message = `${Tanveer} is a Javascript developer`;

Arrow Functions

Arrow functions are defined using a new syntax, the fat arrow (=>) notation. Unlike functions, arrows share the same lexical this as their surrounding code.

Arguments object — no arguments special keyword is defined inside an arrow function.

function regularFunction() {
const arrowFunction = () => { console.log(arguments) }
arrowFunction('c', 'd')
}

regularFunction('a', 'b'); // { 0: 'a', 1: 'b', length: 2 }

this value — The arrow function doesn’t define its own execution context.

const obj = {
foo(items) {
console.log(this); // myObject
const callback = () => {
console.log(this); // myObject
};
items.forEach(callback);
}
};

obj.foo([1, 2, 3]);

Implicit return — If the arrow function contains one expression, and you omit the function’s curly braces, then the expression is implicitly returned

const increment = (num) => num + 1;

increment(30); // => 31

Methods — you can use the arrow function as methods inside classes, the method defined using an arrow binds this lexically to the class instance.

class Animal {
constructor(heroName) {
this.heroName = heroName;
}

logName = () => { console.log(this.heroName); }}

const batman = new Hero('Batman');

Rest Parameters(…)

The rest parameter syntax (...) in front of the last formal parameter means that it will receive all remaining actual parameters in an Array. Rest replaces the need for arguments and addresses common cases more directly

function myFun(a,  b, ...otherArgs) {
console.log("a", a) // a, one
console.log("b", b) // b, two
console.log("otherArgs", otherArgs)
}
myFun("one", "two", "three", "four", "five", "six") // otherArgs, ["three", "four", "five", "six"]

Spread syntax (…)

The spread operator allows you to spread out elements of an iterable object such as an array, map, or set.

let pets = ["Cat", "Dog", "Parrot"];
let bugs = ["Ant", "Bee"];
// Creating an array by inserting elements from other arrays
let animals = [...pets, "Tiger", "Wolf", "Zebra", ...bugs];
console.log(animals); // Cat,Dog,Parrot,Tiger,Wolf,Zebra,Ant,Bee

Default Parameters

If no arguments are provided to the function when it is called default parameters values will be used.

function foo(x=0, y=0) {
···
}

Classes

ES6 Classes formalize the common JavaScript pattern of simulating class-like inheritance hierarchies using functions and prototypes. They are effectively simple sugaring over prototype-based OO, offering a convenient declarative form for class patterns that encourage interoperability.

Constructor — It’s a special method called when an instance of the User class is created

class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
//class instance methods using short-hand method
sayName() {
ChromeSamples.log('Hi, I am a ', this.name + '.');
}
}
let p = new Polygon(200, 300);
p.sayName(); // 'Hi, I am a, Polygon.
console.log('The width of this polygon is ' + p.width);

Static methods — A static method is a function that is bound to the class, not an object. A static method cannot be called from an instance of the class

class User {
...
static staticMethod(){
console.log('I'm static method')
}
}
console.log(sara.staticMethod()) // I'm static method

If you want to dig deeper into the subject, I recommend “Classes in ECMAScript 6” by Dr. Axel Rauschmayer.

Promises

A promise in Javascript is an object which represents the eventual completion or failure of an asynchronous operation. Promises represent a proxy for a value that are getting at some point in the future.

A promise can have 3 states which are the following:

Pending: This is the initial state of the promise, the promise is now waiting for either to be resolved or rejected.

Fulfilled: When the operation is completed succesfully, the promise is fulfilled.

Rejected: When the operation has failed, the promise is rejected.

let myPromise = new Promise((res, rej) => {
console.log('sync executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})


myPromise.then((val) => {
console.log('async executed: ' + val);
}).catch((err) => {
console.log('async executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});


console.log('completed');

ES2020

Promise.allSettled — Since ES2020 you can use Promise.allSettled. It returns a promise that always resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.

const promise1 = Promise.resolve(100)
const promise2 = Promise.reject(new Error("Failed"))
const promise3 = new Promise( res => setTimeout( () => res("success"), 1000))
Promise.allSettled([promise1, promise2, promise3])
.then( values => console.log(values))
//Output
// 0: {status: "fulfilled", value: 100}
// 1: {status: "rejected", reason: Error: Failed}
// 2: {status: "fulfilled", value: "success"}
// length: 3

Promise.any — It returns a promise that is fulfilled by the first promise to resolve successfully and the resulting value is passed back.

If all of them fail, Promise.any throws an exception and executes the reject portion of the promise with a list of all the exceptions.Unlike the Promise.race() method which focuses on the promise which settles the first, the Promise.any() method focuses on the promise which resolves the first.

Modules

An ES6 module is a file containing javascript code. One script is one module.

ES6 modules are automatically strict-mode code, even if you don’t write "use strict"; in them.

import allows the import of functionality from other modules.

import { myLogger, Alligator } from 'app.js';
import myLogger as Logger from 'app.js'; // Exporting with alias
import * as Utils from 'app.js';//Importing all exported members

export keyword labels variables and functions that should be accessible from outside the current module.

export { myFun, myLogger };
export { myLogger as Logger, Alligator } // Exporting with alias
export default function myLogger() { //Default export
console.log(myNumbers, pets);
}

dynamic import returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module’s dependencies, as well as the module itself.

import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});

// This form also supports the await keyword.
let module = await import('/modules/my-module.js');

I recommend “Webpack and Dynamic Imports: Doing it Right” reading for more understanding about dynamic import.

Closing points

There are many changes that have been incorporated into JavaScript starting from ES6. As a developer, it is important to stay up to date with the new features and sharing knowledge.

Happy coding,
Tanveer

--

--