A sinfully short Introduction to ECMAScript 6

ES 6, aka ECMAScript 2015, aka Harmony, is a pretty radical change to the way JS works. This is the first major change since 2009's ES5. Fortunately, the plan from here on out is yearly updates with a relatively small set of features.

The list of changes brought about with ES6 is huge with a capital H. I'm just gonna briefly describe some of the more frequently-encountered ones.

Variables let/const

Let's start with an easy one. var is history. You now gotta use one of let or const, the difference being, const variables can't be reassigned later in the code, which makes sense given the name.

Moreover, these new variable are scoped to the nearest enclosing block, as opposed to the possibly larger nearest function block. This makes writing blocked stuff like for loops inside a function clearer and less error-prone.


Modules import/export

ES6 took a best-of-both-worlds approach to the then-established CommonJS and AMD modules, made popular by Node and RequireJS respectively. There's exactly one file per module and one module per file. Asynchronous loading is supported.

  • By using the export keyword, you can have multiple named exports.
  • You can export anything... constants, variables, classes, functions... you name it.
  • Whatever one module (file) exports, another module can import and re-export.
  • All your imports go at the top of your file.
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5

You can also have a single default export in a file, (except for variables) which makes it slightly easier to import, but I don't recommend it. There's also the provision to rename your exported identifier using the as keyword; so as to avoid namespace clashes. That too should be avoided whenever possible, IMO.

Read more from the source: Axel Rauschmayer's blog


Classes

Let's see what Mozilla has to say:

JavaScript classes introduced in ECMAScript 2015 are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance.

In fact, you really should read their whole article about it.

Simple classes look something like:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }

  get area() {
    return this.calcArea();
  }

  calcArea() {
    return this.height * this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area);

Some notable points:

  • The syntax is Java-esque with class, this and super keywords.
  • Subclassing is possible using super and extendskeywords.
  • There are no separators between members of class definitions. Commas are illegal. Semicolons are legal, but ignored.
  • Class declarations, unlike function declarations, are not hoisted.

There are a hundred things to go over before you can use classes in JS like a pro, but this is probably not the best place for that.


Arrow functions =>

This is most often described as a shorthand, but it's more than that. Basically, instead of writing

function(a, b){
    let c = 23;
    return a + b;
}

You simply write

(a, b) => {
    let c = 23;
    return a + b;
}

It could be even shorter. Parentheses to the left of the arrow can be omitted if and only if you've got a single parameter. The braces and the return keyword to the right of the arrow can be omitted if and only if you've got a single line of expression to return. For instance,

(a) => { return a*2 }could be

a => a*2

In addition to saving several bytes of code, and a providing a nice clean syntax, the arrow function can solve the this problem in most (though not all) cases. So if you're lucky, you won't be needing call() and apply() either.


Promises

Promises are a fancy way to handle asynchronous stuff. Seeing as Angular is gonna force observables down your throat anyway, Promises are not exactly a priority here. But it's an important change, which might be preferable to observables in simple cases, so here's just a basic example.

A promise is something you define after your code with an action to be taken later if it succeeds, and another action if it fails. This promise will either get fulfilled or rejected, after which, it's deemed settled. Until then, it's pending.

To create a promise, you need a callback with two parameters:

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

To use your promise, you need to provide two callbacks to its then function:

promise.then(function(result) {
  console.log(result); // "Stuff worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});

Read more from the source: Jake Archibald's blog


The for-of loop

This loop is designed for the new ES6 construct iterables, which includes, among other things, arrays and strings. It basically makes forEach and for-in obsolete for iterables.

for(let elem of someArray){
   //do something
}

Objects are not iterable, so for-in is still relevant there. However, ES6 objects ship with methods that do return iterables, like Object.keys(), which you can use with for-of as an alternative:

const obj = { k1 : 'v1', k2 : 'v2' };

for (const key of Object.keys(obj)) {
  console.log(key + ": " + obj[key]); // 'k1: v1', 'k2: v2'
}

I think we're good at this point. There's still a lot of stuff we haven't covered. Most notably generators. I've skipped generators because (a) we already have promises and observables to handle our asynchronous stuff and (b) The async/await keywords from ES2017 are gonna make them obsolete for the most part anyway.

A quick rundown of things I've chosen to skip detailing (in addition to generators and iterators):

  • Spread operator(...), rest parameters, default values in parameters, and destructuring arrays/objects, which provide significant syntax upgrades.
  • Template literals (which use backticks). They can include interpolated expressions: Constant stuff with ${variable}

  • The new primitive type: symbol. They're like strings; but are always unique, and hence ideal for property keys, among other use cases. (Caution: They're not serializable, and hence shouldn't be used where JSON data is being transferred)

  • The four new data structures: Maps and WeakMaps (akin to objects); Sets and WeakSets (akin to arrays) .

Additionally, some ES5 primitives have been updated:

  • Global objectsMath, Number and String; among others; get several new properties/methods.
  • Array gets new features, most notably Array.from().
  • Object gets new features, most notably Object.assign().

This list, like this article, is far from comprehensive; but I'm hoping it'll get the ball rolling without overwhelming newcomers too much.

results matching ""

    No results matching ""