Thursday, March 28, 2024

New ECMAScript 2015 Features: Arrows to Tail Calls

The General Assembly of Ecma International recently announced the approval of the ECMAScript 6 Language Specification. Also known as ECMAScript 2015, the spec a is considered to be a major improvement over ES5, with the language specification having almost 600 pages compared to 245 for ES 5.1! Mozilla Firefox has already begun to support many of the new features, while other browsers are slowly getting there. While we’re waiting, let’s go over some of the exciting new additions to the JS language and see what’s in store! This topic will be spread over two installments with part 2 coming in a couple of weeks.

Overview

We won’t be getting into every new ES6 feature here but here are some of the more prominent ones:

  • arrows
  • extended function scope
  • default function parameter values
  • rest parameters
  • iterators
  • the let and const statements
  • (almost) real classes!
  • new-and-improved object literals
  • computed property names
  • duplicate property names
  • function shorthand
  • destructuring assignments
  • template strings
  • destructuring
  • rest and spread
  • generators
  • unicode
  • modules and module loaders
  • map, set, weakmap, weakset
  • proxies
  • symbols
  • subclassable built-ins
  • promises
  • math, number, string, array, object APIs
  • binary and octal literals
  • reflect api
  • tail calls

Arrows

The new arrow function shortcut Identifier => Expression syntax allows you skip typing a lot of function code, including the “function” and “return” keywords, as well as parentheses, braces, and a semicolon.

// ES5
var total = values.reduce(function (a, b) {
  return a + b;
}, 0);

// ES6
var total = values.reduce((a, b) => a + b, 0);

Extended Function Scope

In ES5, inner functions don’t inherit their outer function’s this value. Thus, inside inner functions, the this pointer will either be window or undefined. In ES6, inner functions now inherit the this reference from the enclosing outer function. In the example below, the addAll() method receives this from the enclosing function. Note that the inner function uses arrow notation.

// ES5
{
  ...
  addAll: function addAll(pieces) {
    var self = this;
    _.each(pieces, function (piece) {
      self.add(piece);
    });
  },
  ...
}

// ES6
{
  ...
  addAll: function addAll(pieces) {
    _.each(pieces, piece => this.add(piece));
  },
  ...
}

Default Function Parameter Values

While we’re on the subject of functions, ES6 allows function parameters to be initialized for when they were not explicitly provided by the caller. Previously we would have to check for undefined parameters and assign default values ourselves:

// ES5
function f(x, y) {
  y = y || 42;
  return x + y;
}

// ES6
function f(x, y=42) {
  return x + y;
}

Rest Parameters

Still on the subject of function parameters, Rest parameters provide a more explicit way of identifying functions that take a arbitrary number of parameters. You just prepend an ellipsis (…) to the array variable name:

function add(...values) {
   let sum = 0;

   //this is a new loop type (see below)
   for (var val of values) {
      sum += val;
   }

   return sum;
}

add(2, 5, 3); // => 10

Iterators

You may have noticed in the previous example that the for loop says “of values” and not “in values”. That’s not a typo, but a for-of loop, which allows you to conveniently loop over iterable objects, such as function arguments.

for (let i of new RangeIterator([1, 10])) {
   console.log(i);
}

The let Statement

The above for loop contains another new word: “let”. The let statement allows you to declare variables that are limited in scope to the current block, statement, or expression in which it is used. Conversely, the var keyword defines a variable globally when employed outside of a function or locally to the entire function when contained within one, regardless of block scope.

const x = 1;
var   y = 0;
if (x > y) {
  let z = 12.7 + y;
  var i = z * x;
}
alert(z); //undefined! (out of scope)
alert(i);     //12.7

(Almost) Real Classes!

ES6 finally supports classes…well…sort of. They are really just window dressing over the prototype-based objects that currently exist, but having a standardized declaration syntax makes objects easier to create and use, and promotes OO-style interoperability. In addition to prototype-based inheritance, classes also support super calls, instance and static methods and constructors!

class Dog extends Canine {
  constructor(name) {
    super();
    this.name = name;
  }

  get name() {
    return this.name;
  }

  speak() {
    super.speak();
  }

  static create() {
    return new Dog();
  }
}

Conclusion

Overall, the response of developers to ES6 has been overwhelmingly positive. While I personally may eschew some of the new features, there are more than a few keepers!

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured