ES6 primer for getting started with Angular

ECMAScript is the name of the standard that guides Javascript.

ES6 stands for ECMAScript 6 the latest version of the standard finalized in 2015.

This is the latest version of Javascript and has significantly new features aimed at helping develop and maintain large scale web applications.

While this new version of Javascript doesn’t enjoy as much browser support as it’s predecessor it’s possible to compile ES6 code into ES6 using tools like Babel

Angular 2 in particular makes a lot of use from these features, so if you are planing to get into Angular 2 development it’s a good idea to learn at least some of the features in ES6.

So lets get started!

Variable Declaration

let

There’s a new keyword that let’s you declare variables in Javascript named let. If you recall using var would cause the variables declared to be hoisted. Variables declared using the let keyword are not hoisted and behave in the way most of us would expect.

function productAvailability(item) {
    if (item.quantity > 0) {
        let availability = item.quantity + "is Available"
        return availability;
    }
    // availability is not accessible here
    // if we used var to declare availability it will be available here due to hosting.

    return "Out of stock!";
}

const

With ES6 there is now a way to declare actual constants, using the const keyword.

const PI = 3.14159;
//PI cannot be reassigned
//PI has to be assigned a value at declaration time.

However this constant only makes the variable constant, if you declare a object a constant, you can change it’s properties but you cannot point the variable at another object.

const CAR = {make:"Toyota", model:"Prius"};

CAR.model = "AQUA"; //This is legal and valid

CAR = {make:"Nissan", model:"Cefiro"}; //This is invalid and illegal

The new const keyword behaves in a similar manner to Java’s final keyword.

Default parameters

ES6 now has default parameters built in. No more || logic asigning default values inside functions!

Syntax is pretty simple

function foo(param1 = 0, param2 = calculateDefaultValue()){

}

Object creation and variable assignment

You can use a shortcut to create objects in ES6.

function createCar(){
    let make = "Toyota";
    let model = "Camry";

    return {make, model}; //Previously you had to name them like {make:make, model:model}
}

There are ways we can make assignments from objects to variables shorter as well.

let car = {make:"Toyota", model:"aqua", modelDetails:{year:2010,engineCapacity:"2.4l"}}

//This is how you'd do the assignment traditionally
let carMake = car.make;
let carModel = car.model;

//Now we can use this shortcut
let {carMake:make, carModel:model} = car;

// If your variable names are the same as the object attributes you can write
let {make,model} = car;
//Now you have two variables name make and model populated with the car objects properties named the same.

//You can make nested assignments as well.
let {modelDetails : {year}} = car;
//Now you have a variable named year with the car.modelDetails.year property assigned to it.

//Array element assignment is also possible in order.
let manufacturedYears = ["2009","2010","2011","2012"];
let [year1,year2] = manufacturedYears;
//year1 has a value of 2009, year2 has a value of 2010

Variable arguments

Many languages have clear and obvious support for variable arguments.

With ES6 specification, javascript does too.

Previously you had to use the arguments variable to get extra arguments passed to a function. But this wasn’t very visible or readable.

Now we can use ... operator to pass variable arguments in a more visible way.

function addCars(...cars){
    for(let car in cars){
        carsInFactory.add(car);
    }
}

The ... operator is called the rest operator and can be used in variable assignments as well

let manufacturedYears = ["2009","2010","2011","2012"];

let [firstYear, ...allOtherYears] = manufacturedYears;
//firstYear will have a value of 2009 and the allOtherYears will have the elements from 2010 onwards

String templates

One of the most annoying things to do in javascript is putting together strings. We had to use concatenation to compose a string. Not anymore.

Now you can do string templating using the `` operator like this.

let fullName = `Mr. ${firstName} ${lastName}`;

//Clean Multiline support is available as well. This will help immensely with writing markup.
let welcomeMarkup = `<div>
    <h1>Welcome ${firstName} </h1>
</div>`

Classes and inheritance

Before ES6 you had to use the prototype mechanism to do inheritance, and there was no built in classes.

But now with ES6 we get native support for classes.

Classes, constructors and static methods
class Car{
    constructor(make, model){
      this.make = make;
      this.model = model;
    }

    honk(){
        alert(`Honk from ${this.make} ${this.model}`);
    };

    static wheelCount(){
        return 4;
    }
}

//Creating a new object from Car class.
let mustangGT = new Car("Mustang", "GT");

//Calling the instance method.
mustangGT.honk();

//Calling the static funtion. Can only called directly from the Car class.
Car.wheelCount();

You define a class with the fitting class keyword. And the constructor keyword let’s you define the constructor, in case you aren’t already familiar with constructors, this is the method getting called when you create an object using the new keyword.

You can define a static method using the static keyword. Static methods can be called directly from the class only.

Gettters and setters

Another interesting feature is the ability to designate cleaner getter and setter methods.

A getter is designated using the get keyword, and setter is designated using the set keyword. The getter and setter will be invoked when the property is accessed normally.

class Car{

    constructor(make){
      this.make = make;
    }
    get make(){
        console.log("make property accessed");
        return this.make;
    }

    set make(make){
        console.log("make property changed");
        this.make=make;
    }
}

let car = new Car("Toyota");

//The setter method is invoked. "make property changed" is printed to the console.
car.make = "Nissan";

//The getter method is invoked "make property accessed" is prined to the console.
let make = car.make;
Inheritance

Before ES6 you had to rely on the prototype mechanism to achieve inheritance.

Now there’s a much more readable way.

    class Car{
        constructor(make){
            this.make = make;
            this.speed = 180;
        }

        honk(){
            console.log("Honk Honk");
        }

        fullspeed(){
            console.log("Going at " + this.speed);
        }
    }

    class BMW extends Car{
        constructor(make){
            //Call the super class contructor. Always invoke the super class constructor,
            //omitting this causes an error.
            super(make);

            //If we place any this calls before calling the super contructor, it will throw an error.
            this.navSystem = "NVQ Nav";
        }

        //Overriding the base method from the super class.
        fullspeed(){
            honk();
            super.fullspeed();
        }
    }

    let bmw = new BMW();
    bmw.fullspeed();
    bmw.honk();

You use the extends keyword to define the inheritance relationship. The super keyword is used to refer the super class properties and methods.

Arrow Functions (Lambdas)

Arrow functions are a way to define anonymous functions easily. It’s syntax is shorter than standard function definitions.

It also binds the this value lexically. You use the fat arrow => symbol to declare an arrow function.

The syntax is pretty simple.

() => console.log("Simple arrow"); //No parameters

param1 => console.log("Simple arrow with a parameter"); // Paranthesis is optional if there's only one parameter.

(param1,param2) => console.log("Simple arrow with parameters");

(itemCount) => {
    let newCount = itemCount - 1;
    return newCount; //If there's no statements block then return is implicit, we need explicit return here.
}

function lexicalTest(){
    this.itemCount = 10;

    //Here this keyword is bound lexically, the arrow function doesn't have a new this in it's scope.
    updateCount(() => this.itemCount - 1);
}

The arrow functions will greatly reduce formal code when working with APIs like Promises and collection functions like map.

Maps and Sets

ES6 introduces proper Set and Map collection classes.

Map

The Map class operates as you expect from a Map. It stores key value pairs and provide methods to manipulate the data. There are several key methods.

  1. set(key,value) Adds an element to the map. Takes the key as the first parameter and the value as the second.
  2. get(key) Retrieves a value from the map using the key.
  3. delete(key) Removes a value from the map using the key.
let cars =  new Map();
cars.set(car.id, car); //Adds an element
cars.get(1); //Retrieves the element using the key
cars.delete(1); //Removes the item from the Map using the key

Iterating over a map is easily done using the for...of loop.

    for(car of cars){
        //car is an element with the [key,value] data in that order.
    }

    for(let [carID, car] of cars){
        //carID is the key and car is the object
    }
Set

Set class allows you to hold unique elements in it. The key methods are similar to the Map class.

  1. add(element) Adds the element to the set collection.
  2. delete(element) Deletes the element from the list.
let cars =  new Set();
cars.add(car); //Adds an element to the set
cars.delete(car); //Removes the item from the set

Iterating over a set is easily done using the for...of loop as well.

    for(car of cars){
        //car is an an element in the Set collection.
    }

Something important to note is that the equality in both Map key and Set elements are compared similarly to === except it considers NaN === NaN to be true, allowing us to use NaN as a Map key and Set element.

Modules

ES6 introduces a mechanism for managing modules. Something standard JS lacked. You can achieve this using the export keyword. These are called named exports.

————————car.js————————-

export function analyzeCarPerformance(car){
    //Do whatever
}

export function doEngineTuneUp(car){
    //Do whatever
}

————————-app.js———————–

//import individually
import {analyzeCarPerformance, doEngineTuneUp} from 'car';

//Call the imported methods
analyzeCarPerformance(car);
doEngineTuneUp(car);

You can also use wildcards to import all the functions. You can import into an object and use the said object to invoke the functions.

//import individually
import * as car from 'car';

//Call the imported methods
car.analyzeCarPerformance(car);
car.doEngineTuneUp(car);

You can also give aliases to the functions you import.

//Multiple aliases
import {analyzeCarPerformance as analyzeCar, doEngineTuneUp as doTuneUp} from 'car';

//Call the methods using the aliases given.
analyzeCar(car);
doTuneUp(car);

Sometimes a module will only need to export or expose only one function, value or class. In such instances you no longer needs to use named exports. You can use the default keyword with the export keyword to achieve this.

//car.js file definition
export default function() {
  //Do whatever
}

//main.js
import dFunction from 'car';

dFunction(); //Invokes the default function from car.js file.

There is many more to ES6 than this superficial look we’ve taken at it.

But this should help you get started with Angular 2.

Written on April 7, 2016