donuts
Skip Navigation

5 New Features of JavaScript (ES2015) [Warning: technical blog ahead] If you're not a developer, this post might be a little confusing.

Get the latest web news, tips & tricks in your inbox. We promise never to spam you or sell your email address.

Posted by jared on - Read

5 New Features of JavaScript (ES2015)

[Warning: technical blog ahead]
If you're not a developer, this post might be a little confusing. We share lots of technical details, but feel free to read through or send this to your favorite developer at your company.

ES2015 is ES6 – ES6 is ES2015

Before we get started I want to clear up any ES2015-ES6 confusion. For consistency, I’m only going to be talking about ES2015 as we go from here. It is three more keys to type, but you'll have to trust me that it makes sense. ES2015 (ECMAScript 2015) is the newest version of the ECMAScript standard, and is a significant update, the first major one since ES5 in 2009. Thankfully, the industry is moving away from an index version 6, to a year 2015, with hopes of updating the standard annually.

This update provides some cool stuff out of the box that we’ve all used in other frameworks and through design patterns. I picked out five new features that I can see being the most applicable to the everyday developer. I recommend that you start playing with these today.

1. Variety of Variables

 

I know we all loved our trusty VAR – easy to remember, optional at times, and ready to be used and hoisted anywhere and anytime (global). The latter caused some weird results in JavaScript. ES2015 introduces two new block-scoped variable types LET and CONST.

LET is a mutable variable declaration that has scope in the block which they are defined, as well as any contained sub-blocks. These are great to use inside if/else blocks and loops.

function varFunc() {
if (true) {
var myVar = "global";
}
console.log(myVar);
}
function letFunc() {
"use strict";
if (true) {
let myVar = "block";
}
console.log(myVar); //ReferenceError: myVar is not defined
}
function func() {
"use strict";
let myVar = "out";
if (true) {
let myVar = "in";
console.log(myVar); //in
}
console.log(myVar); //out
}

Run this code

CONST creates a read-only reference to a value in global, functional, or block scope.

"use strict";
function () {
const GREATEST_TV = "Seinfeld";
console.log("The greatest TV show of all time is " + GREATEST_TV)
GREATEST_TV = "The Office"; //TypeError: Assignment to constant variable
// even though that was a close second
const GREATEST_TV = "Some other show"; // SyntaxError: Identifier 'GREATEST_TV' has already been declared
}

Run this code

A variable declared with const is just a read-only reference – that is the big take away here. It does not hold immutable values, it holds read-only references, which means the variable identifier cannot be reassigned.

"use strict";
(function () {
const GEORGE = {
name: "George Costanza",
occupation: "Assistant to the Traveling Secretary"
};
console.log(GEORGE.name + ' is an ' + GEORGE.occupation + '.'); //George Costanza is an Assistant to the Traveling Secretary.
GEORGE.name = "Art Vandelay";
GEORGE.occupation = "Architect";
console.log(GEORGE.name + ' is an ' + GEORGE.occupation + '.'); //Art Vandelay is an Architect.
})();

When you do want the reference value to be immutable, you can use Object.freeze():

"use strict";
(function () {
const GEORGE = Object.freeze({
name: "George Costanza",
occupation: "Unemployed",
residence: "Parents"
});
GEORGE.occupation = "Architect"; //TypeError: Cannot assign to read only property
})();

Run this code

A Quick word on ‘use strict’

In the examples above hopefully you noticed the extra directive in letFunc() and top of most code blocks.

”use strict”;

You should be using this too. Really, just try it - JavaScript loves helping out when it can, sometimes to a fault. By declaring strict mode in your file or functions, you are politely asking your friend to back off a little and let your code do exactly what you are typing. Worst case scenario you get more [specific] errors to debug, which is a good thing.

2. Classes

ES2015 classes finally provides a way to encapsulate and extend code. Everyone already used prototype-based OO patterns for this, but ES2015 gives us not only some syntactical sugar in a declarative form. It also provides inheritance, super calls, instance and static methods, and constructors.

These classes are not introducing any kind of new OO model to JavaScript, they are just "special functions" that you will have to new up to use.

"use strict";
class Checklist {
constructor(name) {
this.name = name;
this.toDos = [];
}
addToDo (note) {
this.toDos.push(note);
}
clearList (note) {
this.toDos = [];
}
}
console.log(typeof Checklist); //function
Checklist(); // TypeError: class constructors must be invoked with 'new'

They can also include static methods.

"use strict";
class Checklist {
/* … */
static getMantra() {
return "Just get in and out!";
}
}
console.log("Remember - " + Checklist.getMantra());

Let’s build on the class above to show some examples of typical class behaviors introduced in ES2015. I’m going to let the code (and comments) speak for itself here.

"use strict";
class Checklist {
constructor(name) {
this.name = name;
this._storeName = "West Side Market";
this.toDos = [];
}

/* getter & setter */
get store() {
return this._storeName;
}
set store(value) {
this._storeName = value;
}

/* getter only */
get numberOfThingsToGet() {
return this.toDos.length;
}

/* public methods */
addToDo (note) {
this.toDos.push(note);
}

clearList (note) {
this.toDos = [];
}

printList() {
if (this.toDos.length > 0) {
this.toDos.forEach(t =>
console.log(`- ${t}`));
} else {
console.log("Turn around, you don't need anything in there!");
}
}

static getMantra() {
return "Just get in and out!";
}
}
var list = new Checklist("Groceries");
console.log(`Go to ${list.store}`); //Go to West Side Market
list.addToDo('Get Apples'); list.addToDo('Get Bananas'); list.addToDo('Get Pierogies'); list.addToDo('Get Meats, especially bacon');
console.log(`I need to get to ${list.numberOfThingsToGet} items`); //I need to get to 4 items

list.printList(); /* - Get Apples - Get Bananas - Get Pierogies - Get Meats, especially bacon */
console.log("Remember - " + Checklist.getMantra()); //Remember - Just get in and out!

We can even create inheritance relationship using the extends and super keywords. Extends sets up the relationship between parent and child classes. Super invokes the parent class constructor, it is required even if the parent object does not use it. Invoking the super constructor is what creates the new this object to be used in the child.

class FamilyChecklist extends Checklist {
constructor(name, owner, store) {
super(name);
this._storeName = store;
this.taskRunner = owner;
}
printList() {
console.log(`${this.taskRunner} needs to go to ${this._storeName} to get: `)
this.toDos.forEach(t =>
console.log(`> ${t}`));
}
}

var josephsList = new FamilyChecklist("Landscaping", "Joseph", "Outdoor World");

josephsList.addToDo("Get Annuals");
josephsList.addToDo("Get Mulch");
josephsList.addToDo("Get Garden Vegetables");

josephsList.printList(); /* Joseph needs to go to Outdoor World to get: > Get Annuals > Get Mulch > Get Garden Vegetables */

console.log("Remember - " + Checklist.getMantra());

Run this Classes code

3. Arrow Syntax

The cousin of a C# lambda expression, arrow function expressions provide us with benefits for writing functions quicker, writing cleaner code, and lexically binding this.

/* Start writing your function quicker */
var oldFunc = function (val1) {
//do something useful and concise
}

var newFunc = (val1) => {
//start writing something useful and concise a little quicker
}

/* A nice and clean lambda expression */
var colors = ['Orange','Blue','Green','Yellow'];
var longLength = colors.map(function(color){ return color.length }); //[6, 4, 5, 6]
var cleanLength = colors.map( c => c.length); //[6, 4, 5, 6]

If you didn’t already lookup lexical, like I had to – Arrow function expressions are here to help keep the elusive this where it was. We typically handled a change in this with self variables. Now we can use the arrow function lexical scoping to better keep this and that (self).

var team = { 
_name: "Cavs",
_starters: ["LeBron James","Kevin Love","Kyrie Irving","J.R. Smith","Tristan Thompson"],

announceStarters() {
this._starters.forEach(s =>
console.log("Now Starting for your " + this._name + ", " + s));
}
}

team.announceStarters();

Run this Arrow Syntax code

4. Promises

A Promise is an asynchronous function that will complete in the future. This type of call allows for parallel processing and to proxy something not yet set in code. So using them on an async method is promising to return something in the future. They allow you to associate handlers to an async action's resulting success or failure.

Promises extract our callback function from the parameters we pass to a function – helping separate our concerns. We can increase our code readability and reduce our callback chains (avoiding those ugly Christmas trees).

function asyncMethod(msg, callback){
setTimeout(function() {
console.log(msg);
cb();
}, 500);
}

asyncMethod('open DB', function() {
asyncMethod('query data', function() {
asyncMethod('validate data', function() {
asyncMethod('update data', function() {
});
});
});
}); //^Pyramid/Christmas Tree code

Our callbacks cleaned up with promises:

asyncMethod('open DB')
.then((data) => asyncMethod('query data')
.then((data) => asyncMethod('validate data')
.then((data) => asyncMethod('update data')
.error((data) => {
// error handling
});

You can read the details at MDN, but here are some basics:

States - mutually exclusive
  • pending: initial state, before a result is ready.
  • fulfilled: result is ready - operation completed successfully.
  • rejected: operation failed during computation.
Methods - reactions to state changes
  • then(): callback notified of a fulfilled promise
  • catch(): callback handler of a rejected promise

5. Template Strings

One of the most common system functions in C# I find myself using is string.Format(). I always have things to pull and push together, and it provides a clean way to build up string values. Save yourself from the “+” concatenations by using the backtick (`) in ES2015 for constructing strings:

"use strict";
(function() {
var code = "JavaScript";
var version = "ES2015";
console.log(`I am writing some ${code} in ${version}`);
})();

Transpiling

Like everything with the modern web you always have to ask yourself, should I use ES2015 now or wait?

The good news is that native ES2015 support in browsers such as Chrome, Firefox, and Edge is continuously getting better and better. Here’s a great compatibility table, to use as a reference. Not surprisingly, Internet Explorer 6-9 is not listed since they won’t be getting ES6 features – ever! But do not fear, transpilers are here! These beautiful creations can convert ES2015 code to ES5. So by integrating a transpiler into your development workflow you can use these fancy and helpful new features, while getting ES5 conversion automatically behind the scenes!

Dan Wahlin does a great job laying out how to get started using transpilers.

Resources

ECMAScript 6 Compatibility Table, github http://kangax.github.io/compat-table/es6/

See the ES2015 standard for full specification of the ECMAScript 2015 language.

@JaredtheNerd's (not this Jared) presentation at CodeMash 2015

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Search this site