10 coolest features of ES6

EcmaScript 2015 comes with a lot of new features most of which are placed in order to fill the gaps existing in ES5 and prior versions. In this post we will go through 9 most handy features introduced in ES6 with various examples.

 

As of the time I’m writing this post, most browsers still don’t support ES6 and have not yet implemented any of these features. To play more with ES6 and see it in action you can go to: http://www.es6fiddle.net or you can use tools like traceur or babel along with task runners such as grunt or gulp to automatically transpile the code into executable ES5-based Javascript.

1) Classes and Inheritance

The new class is an attempt to push Javascript prototypal inheritance syntax closer to other common programming languages. Though under the hood class is still a JS object and is inherently different from class concept in other programming languages. We now can enjoy this similar syntax and avoid having to use function methods and prototypes to make up for classes and inheritance.

// Class definition
class Person {
// class constructor which will be called every time
// a new object is being instantiated
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.age = 0;
}
fullName() {
return this.firstName + ' ' + this.lastName;
}
// setter method
setAge(age) {
this.age = age;
}
// getter method
getAge() {
return this.age;
}
}
// Child class which inherits all the properties
// and methods of the parent class
class Employee extends Person {
constructor(firstName, lastName) {
// this will call the constructor method of the parent class
super(firstName, lastName);
this.position = null;
}
getPosition() {
return this.position;
}
setPosition(position) {
this.position = position;
}
logDetails() {
console.log(
'Employee: ' + this.fullName() +
', age: ' + this.getAge() +
', position: ' + this.position
);
}
}
// New object is created from Employee
var john = new Employee('John', 'Smith');
john.setPosition('Accountant');
john.setAge(35);
john.logDetails();

2) let vs. var

A long-standing issue with Javascript is the way variable declaration works with “var”. Main source of confusion is the concept of hoisting in Javascript where a variable can be used before it’s being defined. A common example where things could go wrong is inside a for loop:

func = [];
for (var i = 0; i < 5; i++) {
func.push(function() {
console.log(i);
});
}
func.forEach(function(f) {
f();
});

Since variables declared by var are accessible outside the for block, while the execution context reaches f() and subsequently tries to execute console.log(i), at that point i equals 5. See below how using let in the for loop changes the result.
Screen Shot 2016-04-17 at 6.54.00 PM

3) const

Similar to let, const offers the concept of scope blocking, the difference is that as the name implies const variables are immutable and can only be set once.
Screen Shot 2016-04-17 at 7.26.34 PM

const is real helpful when we need to declare variables that are going to be fixed all the time such as for example api key, api URL, etc.

4) String templates (template literals)

This is pretty handy when dealing with string and variables in an expression without having to concatenate any text with any number of variables and not to mention the coercion issue.

var x = 1;
var y = 2;
var equation = `${ x } + ${ y } = ${ x + y }`
console.log(equation);

Screen Shot 2016-04-17 at 1.05.04 PM

5) Default value for function params

Up until ES6, there was no way to have a default value for a function argument. If a given argument is passed without a value, it would be evaluated as ‘undefined’ in the execution context and therefor we had to explicitly handle this condition right at the beginning of the code block in case the parameter value equals ‘undefined’.

function greet(greeting, name = "Rayan") {
console.log(greeting + ', ' + name);
}
greet("Hello");

Screen Shot 2016-04-17 at 1.17.44 PM

6) Arrow Functions

This is another cool feature that helps writing much smaller codes.

let square = x => x * x;
let add = (a, b) => a + b;
let pi = () => 3.1415;
console.log(square(5));
console.log(add(3, 4));
console.log(pi());

the result is:

25
7
3.1415

In above example, ‘x => x * x’ is the equivalent of the following piece of code:

var multiply = function(x) {
return x * x;
}
var evens = [2,4,6,8,10,20,30];
var fives = [];
// expression syntax
var nums = evens.map((v, i) => v + i);
console.log(nums);
// statement syntax
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});
console.log(fives);
// => 2,5,8,11,14,25,36
// => 5,25

Another benefit of using arrow functions is the that unlike functions, arrows share the same lexical this as their surrounding code. As we all know, an common issue with this variable inside an object method is accessing this inside a nesting callback function. The obvious work-around is to copy “this” variable to another variable which then will be accessible inside the callback:

var person = {
  name: "",
  friends: [],
  printFriends: function() {
    var that = this;
    this.friends.forEach(function(v) {
      console.log(that.name + " knows " + v);
    });
  }
};
// Set the stage
person.name = "Bill";
person.friends = ["Tom", "Sam", "Simon"];
console.log(person.printFriends());
//Bill knows Tom
//Bill knows Sam
//Bill knows Simon

Using arrow function this code would be simplified to:

var person = {
  name: "",
  friends: [],
  printFriends() {
    this.friends.forEach(v =>
      console.log(this.name + " knows " + v)
    );
  }
};
// Set the stage
person.name = "Bill";
person.friends = ["Tom", "Sam", "Simon"];
console.log(person.printFriends());

7) Shorthand Properties

let firstName = "John";
let lastName = "Lindquist";
let person = {firstName, lastName}
console.log(person);
//>>> { firstName: 'John', lastName: 'Lindquist' }

8) Destructed Assignment

var people = [
  {
    "firstName": "Clinton",
    "lastName": "Ruiz",
    "phone": "1-403-985-0449",
    "email": "pharetra@facilisislorem.org",
    "address": "Ap #829-3443 Nec St."
  },
  {
    "firstName": "Skyler",
    "lastName": "Carroll",
    "phone": "1-429-754-5027",
    "email": "Cras.vehicula.alique@diamProin.ca",
    "address": "P.O. Box 171, 1135 Feugiat St."
  },
  {
    "firstName": "Kylynn",
    "lastName": "Madden",
    "phone": "1-637-627-2810",
    "email": "mollis.Duis@ante.co.uk",
    "address": "993-6353 Aliquet, Street"
  },
  {
    "firstName": "Chaney",
    "lastName": "Edwards",
    "phone": "1-397-181-4501",
    "email": "rutrum@Nullamlobortis.net",
    "address": "P.O. Box 342, 9574 Egestas Street"
  }
]
people.forEach(({firstName}) => console.log(firstName))
var [,Skyler] = people;
function logEmail({email}){
  console.log(email);
}
logEmail(Skyler);

9) Rest + Rest

function add(a, b) {
    return a + b;
}
let nums = [5, 4];
console.log(add(...nums));
>>> 9

10) Generators

function* greet(){
    console.log(`You called 'next()'`);
    yield "hello";
}
let greeter = greet();
console.log(greeter);
let next = greeter.next();
console.log(next);
let done = greeter.next();
console.log(done);
//------------
function* greet(){
    let friendly = yield "How";
    friendly = yield friendly + "are";
    yield friendly + "you?";
}
var greeter = greet();
console.log(greeter.next("first").value);
console.log(greeter.next(" the heck ").value);
console.log(greeter.next(" silly ol'").value);
//-----------
function* graph(){
    let x = 0;
    let y = 0;
    while(true){
        yield {x:x, y:y}
        x += 2;
        y += 1;
    }
}
var graphGenerator = graph();
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);
console.log(graphGenerator.next().value);

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *