Life as a developer

ES 2015 – Worth the wait?

Part II

This is a summary of a presentation about ES 2015 that I held for the Trondheim Developer Conference(TDC) 2015. Check out my presentation on Vimeo, but I have to warn you, it is in Norwegian.

This is part two of two.
Part I – Short history and overview
Part II – Examples

let

Let’s (no pun intended) take a look at how var (available in both ES 5 and ES 2015) works inside an if block.


function oldFunction(){
    if(true){
        var a = 3;
    }
    console.log(a);
}

What will happen when we run this function?

Output returns 3
In other languages this will cast an exception. Which in my opinion is the correct way to handle this.


function oldFunction(){
    var a; // hoisted
    if(true){
        var a = 3;
    }
    console.log(a); // 3
}

This is what is actually happening behind the scenes. The a variable is “hoisted” up to the top of the function. Now we are able to call it outside the scope of where it was defined. This can lead to confusion and ultimately bugs. As Douglas Crockford notes

A variable introduced anywhere in a function is visible everywhere in the function. JavaScript’s blocks confuse experienced programmers and lead to errors because the familiar syntax makes a false promise.


function oldFunction(){
    if(true){
        var a = 3;
    }
    console.log(a);
    var a = 5;
    console.log(a);
}

Here we are re-declaring a variable. We would assume that this would cause an issue. Instead this is the output we get

3
5

With ES 2015 we get a new type of variables, namely let.


function newFunction(){
    if(true){
        let a = 4;
    }
    console.log(a);
}

If we try to run this we get

ReferenceError: a is not defined

This is the behaviour that is expected of var.


function newFunction(){
    let b = 1;
    console.log(b); 
    let b = 2;
}

Similarly, if we try to redeclare a variable, we get this

SyntaxError: redeclaration of let b

const

ES 2015 also introduces const, as a new keyword to declare variables. As the name suggest, it is a constant.


function myFunction(){
    const a = 1;
    a = 2;
    console.log(a);
}

Here we try to assign an already assigned constant, which yields

TypeError: invalid assignment to const 'a'

Beware of different implementations in browsers. FireFox will throw an error, while Chrome just ignores the second assignment.

Destructuring

ES 5

var array = [1, 2, 3];
var a = array[0];
var b = array[1];
var c = array[2];

console.log(a+','+b+','+c); // 1,2,3

With ES 2015 this can be done withdestructuring. Destructuring is a way of picking out data from objects or arrays.

From an array

let [a, b, c] = [1, 2, 3];
console.log(‘${a},{b},{c}’);

Here we are creating three variables (a,b,c) and assigns them the values from the array. Output

1,2,3
Using skip inside an array

let [d,, e] = [4, 5, 6];
console.log(‘${d},{e}’);

We can skip values from the array with a comma.

4,5
Using rest keyword

let [f, …g] = [7, 8, 9, 10];
console.log(g);

With the rest keyword (...), we are picking the values that are left after 7 has been assigned to f.

[8, 9, 10]
Retrieve properties

Destructuring really shines when it comes to large set of json objects where you are only looking for a small subset of the properties.


function getPersonData(){
    return { 
        firstName: 'Han', 
        lastName: 'Solo', 
        bestFriend: 'Chewbacca'
    }; 
}
let {firstName: fn, lastName: ln} = getPersonData();
console.log(fn);
console.log(ln);

Here we are picking out firstName and lastName from the object and assigns it to a new set of variables (fn and ln).

Han
Solo

Default parameter

ES 5

function oldDefault(a, b){
    a = a === undefined ? 1 : a;
    b = b || 2;
    console.log(a + ',' + b);
}

oldDefault();
oldDefault(3,4);

Output

1,2
3,4

It is not the most elegant way to handle default parameters, but it works.

ES 2015

function newDefault(a = 1, b = 2){
    console.log(`${a},{b}`);
}

newDefault();
newDefault(3,4);

Output

1,2
3,4

This is a better way of solving it and should be familiar to C# or CoffeeScript developers.

Rest parameters

The old way

function oldFunction(a, b){
    var result = Array.prototype.slice.call(arguments, oldFunction.length);
    console.log(result);
}

oldFunction('a', 'b', 'c');

Output

["b","c"]

This seems like JavaScript wizardry, and many developers are unfamiliar with this way of emulating rest parameters.

ES 2015

function newFunction(a, ...b){
    console.log(b.join(' '));
}
newFunction('a', 'b', 'c');

Output

b c

Once again this is syntax that is familiar to developers of other languages.

Arrow functions

ES 5

function oldFunction(){
    return 1;
}
var result = oldFunction();
ES 2015

let result = () => 1;

A much simpler syntax and loved by C# (lambdas) and CoffeeScript(fat arrow) developers. As long as you don’t use curly braces, you don’t need to use return. Be aware when refactoring old functions into arrow functions, especially where this is involved.

With parameters

let arrowFunction = (a, b) => {
    console.log(`${a},{b}`);
}
arrowFunction(1, 2);

Output

1,2

Arrow functions accepts zero or many parameters. You can drop the parentheses if you use only one parameter, but I suggest you leave them there.

classes

This is a big one. Long awaited/dreaded by developers, depending whether you are a developer coming to JavaScript from a object-oriented language, or if you are a JavaScript purist.

ES 5

As with many other features, creative developers have found ways to “adopt” features that they missed coming from other languages.


function Person() { 
    this.firstName = 'James';
    this.lastName = 'Skywalker';
} 

function Jedi() { 
    this.firstName = 'Luke'; 
} 

var p = new Person(); 
console.log(p.firstName); // James
var j = new Jedi(); 
j.prototype = p; 
console.log(j.firstName); // Luke
console.log(j.lastName); // Skywalker 

Using prototype you can also emulate inheritance.

ES 2015

class Jedi extends Person{
    constructor(fistName, lastName, ship){
        super(firstName, lastName);
        this.ship = ship;
    }   
}

let jedi = new Jedi('Luke', 'Skywalker', 'X-Wing');

With ES 2015 you get constructors, are able to call a parent constructor with super and can inherit from base classes using extends.


class Person{
    constructor(firstName, lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    static printName(person){
        console.log(person.firstName + ' ' + person.lastName);
    }
}
let person = new Person('Inigo', 'Montoya');
Person.printName(person); // Inigo Montoya

Static methods are also supported, but not static properties.

promises

Another very useful feature is promises . You might be familiar with promises from a library called Q, or from Angular having a similar service for promises . A promise is a way to avoid large number of callbacks, or the pyramid of doom as it is referred to.
A promise accepts a callback function with a resolve parameter and a reject parameter. You call the resolve function when the operation is complete successfully, or reject if something went wrong .


var promise = new Promise(function(resolve, reject) {
    ...
    if(success){
        resolve('done');
    }
    else{
        reject('failed');
    }
});

return promise;

var promise = new Promise(function(resolve, reject) {
    ...
});

return promise;

promise.then(function(result){
    console.log(result); // done
}, function(err){
    console.log(err); // failed
});

Shows how you can use a promise . On a promise object, you have a then method, but also a catch method to intercept rejections .

for .. of


let array = [1, 2, 3];
for(let value of array){
    console.log(value);
}

Output

1
2
3

We also got a new loop in for..of. You can iterate overthe values ​​of a iterable object , as shown here, an array .

generators



function *generatorFunction(){
    yield 1;
    yield 2;
    yield 3;
}

for(let value of generatorFunction()){
 console.log(value);   
}

Output

1
2
3

You can also create your own iterable functions with generator functions. You need to mark a generator function with a * before the function name .
Generators uses yield to return values. Along with the value we get a boolean variable that let’s know if it is done or not.

Summary

So has 6 years of waiting been worth it? With EcmaScript 2015, we get more understandable code and a lot of long-awaited features. There are featured beyond what I have covered in this post. They have looked to other languages and adopted features that JavaScript developers already have shoehorned into their code. External packages used for promises or modules can now be dropped as this is brought into the language itself. The consensus amongst developers is that ES 2015 is a step in the right direction, and I only hope that we don’t have to wait another 6 years for next version.

goldnarms

Arnstein Johansen is a .NET Developer with a speciality in web development, but he also dabbles in mobile development and everything new and exciting. Arnstein works for Itema AS, a mid-size consultant agency in Trondheim. Itema has 25 consultants and recently won the prize for Norway's best workplace. He likes to share his knowledge by holding talks for others, either it is clients, colleagues or likeminded developers in user groups. He has hands-on experience from large projects, the latest from Urørt where he leads a team of developers creating a music service used by around 100000 users.

One Comment

  1. Pingback: ES 2015 - Worth the wait? - CodeJunkiiCodeJunkii

Leave a reply