Fork me on GitHub

ECMAScript 6

ES6

Examples of all features in ECMAScript 6


This page shows examples of all features in ECMAScript 6. They are based on examples from the site http://es6-features.org.

All credits to http://es6-features.org.

The GitHub repository is available at https://github.com/gatosnake/es6-examples.

All examples are executed in this page, just open the developer tools in your browser and look at the console ;) . If your browser does not support ES6 code, go to this link that has the same code compiled to ES5.

Constants


Constants

Support for constants (also known as "immutable variables"), i.e., variables which cannot be re-assigned new content. Notice: this only makes the variable itself immutable, not its assigned content (for instance, in case the content is an object, this means the object itself can still be altered).

Code
const PI = 3.141593;
console.log(PI > 3.0);
Result
true

Scoping


Block-Scoped Variables

Block-scoped variables (and constants) without hoisting.

Code
let a = new Array('a', 'b', 'c');
let b = new Array('d', 'e', 'f');

let x = new Array('1', '2');
let y = new Array('3', '4');

for (let i = 0; i < a.length; i++) {
  let x = a[i];
  console.log(`Value x[${i}]:`, x);
}
for (let i = 0; i < b.length; i++) {
  let y = b[i];
  console.log(`Value y[${i}]:`, y);
}

console.log(`Array x:`, JSON.stringify(x));
console.log(`Array y:`, JSON.stringify(y));

let callbacks = []
for (let i = 0; i <= 2; i++) {
  callbacks[i] = function() {
    return i * 2;
  }
}
console.log(`Compare callback[0] === 0:`, callbacks[0]() === 0);
console.log(`Compare callback[1] === 2:`, callbacks[1]() === 2);
console.log(`Compare callback[2] === 4:`, callbacks[2]() === 4);
Result
Value x[0]: a
Value x[1]: b
Value x[2]: c
Value y[0]: d
Value y[1]: e
Value y[2]: f
Array x: ["1","2"]
Array y: ["3","4"]
Compare callback[0] === 0: true
Compare callback[1] === 2: true
Compare callback[2] === 4: true

Block-Scoped Functions

Block-scoped function definitions.

Code
function foo() {
  return 1;
}
console.log(`Compare foo() === 1:`, foo() === 1);

{
  function foo() {
    return 2;
  }
  console.log(`Compare foo() === 2:`, foo() === 2);
}

console.log(`Compare foo() === 1:`, foo() === 1);
Result
Compare foo() === 1: true
Compare foo() === 2: true
Compare foo() === 1: true

Arrow Functions


Expression Bodies

More expressive closure syntax.

Code
let evens = new Array(1, 2, 3);

let odds = evens.map(v => v + 1);
let pairs = evens.map(v => ({
  even: v,
  odd: v + 1
}));
let nums = evens.map((v, i) => v + i);

console.log(`Array odds:`, JSON.stringify(odds));
console.log(`Array pairs:`, JSON.stringify(pairs));
console.log(`Array nums:`, JSON.stringify(nums));
Result
Array odds: [2,3,4]
Array pairs: [{"even":1,"odd":2},{"even":2,"odd":3},{"even":3,"odd":4}]
Array nums: [1,3,5]

Statement Bodies

More expressive closure syntax.

Code
let nums = new Array(2, 5, 3, 6, 8, 4, 5, 1, 5);
let fives = new Array();

nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

console.log(`Array fives:`, JSON.stringify(fives));
Result
Array fives: [5,5,5]

Lexical This

More intuitive handling of current object context.

Code
let example = {
  nums: [2, 5, 3, 6, 8, 4, 5, 1, 5],
  fives: [],
  getFives: function() {
    this.nums.forEach((v) => {
      if (v % 5 === 0)
        this.fives.push(v);
      });
  }
}

example.getFives();

console.log(`Array example.nums:`, JSON.stringify(example.fives));
Result
Array example.nums: [5,5,5]

Extended Parameter Handling


Default Parameter Values

Simple and intuitive default values for function parameters.

Code
function function1(x, y = 7, z = 42) {
  return x + y + z;
}
console.log(`Compare function1() === 50:`, function1(1) === 50);
Result
Compare function1() === 50: true

Rest Parameter

Aggregation of remaining arguments into single parameter of variadic functions.

Code
let a = new Array(1, 2, 3, 4, 5);

function function2(x, y, ...a) {
  return (x + y) * a.length;
}
console.log(`Compare function2() === 9:`, function2(1, 2, "hello", true, 7) === 9);
Result
Compare function2() === 9: true

Spread Operator

Spreading of elements of an iterable collection (like an array or even a string) into both literal elements and individual function parameters.

Code
function function2(x, y, ...a) {
  return (x + y) * a.length;
}

let params = ["hello", true, 7];
console.log(`Compare function2() === 9:`, function2(1, 2, ...params) === 9);
let other = [1, 2, ...params];
console.log(`Array other:`, JSON.stringify(other));

let str = "foo";
let chars = [...str];
console.log(`Array chars:`, JSON.stringify(chars));
Result
Compare function2() === 9: true
Array other: [1,2,"hello",true,7]
Array chars: ["f","o","o"]

Template Literals


String Interpolation

Intuitive expression interpolation for single-line and multi-line strings. (Notice: don't be confused, Template Literals were originally named "Template Strings" in the drafts of the ECMAScript 6 language specification)

Code
let customer = {
  name: "Foo"
};

let card = {
  amount: 7,
  product: "Bar",
  unitprice: 42
};

let message = `Hello ${customer.name},
want to buy ${card.amount} ${card.product} for
a total of ${card.amount * card.unitprice} bucks?`;

console.log(`Value message:`, message);
Result
Value message: Hello Foo,
want to buy 7 Bar for
a total of 294 bucks?

Custom Interpolation

Flexible expression interpolation for arbitrary methods.

Code
function get(array, param1, param2) {
  console.log(`Value params get():`, JSON.stringify(array), param1, param2);
  let url = `${array[0]}${param1}${array[1]}${param2}`;
  console.log(`Value url:`, url);
}

let bar = `Hola`;
let baz = `Mundo`;
let asd = `Cristhian`;

get `http://example.com/foo?bar=${bar + baz}&quux=${asd}`;
Result
Value params get(): ["http://example.com/foo?bar=","&quux=",""] HolaMundo Cristhian
Value url: http://example.com/foo?bar=HolaMundo&quux=Cristhian

Raw String Access

Access the raw template string content (backslashes are not interpreted).

Code
function quux(strings, ...values) {
  console.log(`Compare strings[0] === "foo\\n":`, strings[0] === "foo\n");
  console.log(`Compare strings[1] === "bar":`, strings[1] === "bar");
  console.log(`Compare values[0] === 42:`, values[0] === 42);
  console.log(`Compare strings.raw[0] === "foo\\\\n":`, strings.raw[0] === "foo\\n");
  console.log(`Compare strings.raw[1] === "bar":`, strings.raw[1] === "bar");
}
quux `foo\n${ 42 }bar`;

console.log(`Compare String.war:`, String.raw `foo\n${ 42 }bar` === "foo\\n42bar");
Result
Compare strings[0] === "foo\n": true
Compare strings[1] === "bar": true
Compare values[0] === 42: true
Compare strings.raw[0] === "foo\\n": true
Compare strings.raw[1] === "bar": true
Compare String.war: true

Extended Literals


Binary & Octal Literal

Direct support for safe binary and octal literals.

Code
console.log(`Compare binary 0b111110111 === 503:`, 0b111110111 === 503);
console.log(`Compare octal 0o767 === 503:`, 0o767 === 503);
Result
Compare binary 0b111110111 === 503: true
Compare octal 0o767 === 503: true

Unicode String & RegExp Literal

Extended support using Unicode within strings and regular expressions.

Code
console.log(`Compare "𠮷".length === 2:`, "𠮷".length === 2);
console.log(`Compare "𠮷".match(/./u)[0].length === 2:`, "𠮷".match(/./u)[0].length === 2);
console.log(`Compare "𠮷" === "\\uD842\\uDFB7":`, "𠮷" === "\uD842\uDFB7");
console.log(`Compare "𠮷" === "\\u{20BB7}":`, "𠮷" === "\u{20BB7}");
console.log(`Compare "𠮷".codePointAt(0) == 0x20BB7:`, "𠮷".codePointAt(0) == 0x20BB7);
for (let codepoint of "𠮷") console.log(`Value codepoint:`, codepoint);
Result
Compare "𠮷".length === 2: true
Compare "𠮷".match(/./u)[0].length === 2: true
Compare "𠮷" === "\uD842\uDFB7": true
Compare "𠮷" === "\u{20BB7}": true
Compare "𠮷".codePointAt(0) == 0x20BB7: true
Value codepoint: 𠮷

Enhanced Regular Expression


Regular Expression Sticky Matching

Keep the matching position sticky between matches and this way support efficient parsing of arbitrary long input strings, even with an arbitrary number of distinct regular expressions.

Code
let message = "My name is Foo and my lastname is Bar."
let pattern = /my [a-zA-Z]+/y;

console.log(`Return pattern /my [a-zA-Z]+/y:`, JSON.stringify(pattern.exec(message)));

pattern.lastIndex = 19;

console.log(`Return pattern /my [a-zA-Z]+/y:`, JSON.stringify(pattern.exec(message)));
console.log(`Return pattern /my [a-zA-Z]+/y:`, JSON.stringify(pattern.exec(message)));
Result
Return pattern /my [a-zA-Z]+/y: null
Return pattern /my [a-zA-Z]+/y: ["my lastname"]
Return pattern /my [a-zA-Z]+/y: null

Enhanced Object Properties


Property Shorthand

Shorter syntax for common object property definition idiom.

Code
let x = 1;
let y = 2;

let obj = {
  x,
  y
};

console.log(`Value obj:`, JSON.stringify(obj));
Result
Value obj: {"x":1,"y":2}

Computed Property Names

Support for computed names in object property definitions.

Code
let quux = () => ` foo`;

let obj2 = {
  foo: "bar",
  ["baz" + quux()]: 42
};

console.log(`Value obj2:`, JSON.stringify(obj2));
Result
Value obj2: {"foo":"bar","baz foo":42}

Method Properties

Support for method notation in object property definitions, for both regular functions and generator functions.

Code
let obj3 = {
foo(a, b) {
  a + b;
},
bar(x, y) {
  x * y;
},
* quux2(x, y) {
  x + y;
}
};

console.log(`Value obj3:`, obj3);
Result
Value obj3: Object {foo: function, bar: function, quux2: function}

Destructuring Assignment


Array Matching

Intuitive and flexible destructuring of Arrays into individual variables during assignment.

Code
var list = [1, 2, 3];
var [a, , b] = list;
console.log(`Value a:`, a);
console.log(`Value b:`, b);

[b, a] = [a, b];
console.log(`Value a:`, a);
console.log(`Value b:`, b);
Result
Value a: 1
Value b: 3
Value a: 3
Value b: 1

Object Matching, Shorthand Notation

Intuitive and flexible destructuring of Objects into individual variables during assignment.

Code
function getASTNode() {
  return {op: 1, lhs: 2, rhs: 3};
};

var {op, lhs, rhs} = getASTNode();

console.log(`Value op:`, op);
console.log(`Value lhs:`, lhs);
console.log(`Value rhs:`, rhs);
Result
Value op: 1
Value lhs: 2
Value rhs: 3

Object Matching, Deep Matching

Intuitive and flexible destructuring of Objects into individual variables during assignment.

Code
function getASTNode2() {
  return {op: 1, lhs: {op: 2}, rhs: 3};
};

var {op: a, lhs: {op: b}, rhs: c} = getASTNode2();

console.log(`Value a:`, a);
console.log(`Value b:`, b);
console.log(`Value c:`, c);
Result
Value a: 1
Value b: 2
Value c: 3

Object And Array Matching, Default Values

Simple and intuitive default values for destructuring of Objects and Arrays.

Code
var obj = {a: 1};
var {a, b = 2} = obj;

console.log(`Value a:`, a);
console.log(`Value b:`, b);

var list = [1];
var [x, y = 2] = list;

console.log(`Value x:`, x);
console.log(`Value y:`, y);
Result
Value a: 1
Value b: 2
Value x: 1
Value y: 2

Parameter Context Matching

Intuitive and flexible destructuring of Arrays and Objects into individual parameters during function calls.

Code
function f([name, val]) {
  console.log(name, val);
}

function g({name: n, val: v}) {
  console.log(n, v);
}

function h({name, val}) {
  console.log(name, val);
}

f(["bar", 42]);
g({name: "foo", val: 7});
h({name: "bar", val: 42});
Result
bar 42
foo 7
bar 42

Fail-Soft Destructuring

Fail-soft destructuring, optionally with defaults.

Code
var list = [7, 42];
var [a = 1, b = 2, c = 3, d] = list;
console.log(`Compare a === 7:`, a === 7);
console.log(`Compare b === 42:`, b === 42);
console.log(`Compare c === 3:`, c === 3);
console.log(`Compare d === undefined:`, d === undefined);
Result
Compare a === 7: true
Compare b === 42: true
Compare c === 3: true
Compare d === undefined: true

Modules


Value Export/Import

Support for exporting/importing values from/to modules without global namespace pollution.

Code
//  lib/math.js
export function sum (x, y){
  return x + y;
};
export var pi = 3.141593;

//  someApp.js
import * as math from "./lib/math";
import { sum, pi } from "./lib/math";

console.log("2π = ", math.sum(math.pi, math.pi));
console.log("2π = ", sum(pi, pi));
Result
2π =  6.283186
2π =  6.283186

Default & Wildcard

Marking a value as the default exported value and mass-mixin of values.

Code
//  lib/mathplusplus.js
export * from './math';
export var e = 2.71828182846;
export default (x) => Math.exp(x);

//  someApp.js
import exp, { pi, e } from './lib/mathplusplus';
console.log(`e:`, e);
console.log(`e^{π}:`, exp(pi));
Result
e: 2.71828182846
e^{π}: 23.140700648952773

Classes


Class Definition

More intuitive, OOP-style and boilerplate-free classes.

Code
class Shape {
  constructor(id, x, y) {
    this.id = id;
    this.move(x, y);
  }
  move(x, y) {
    this.x = x;
    this.y = y;
  }
  getPos() {
    return {
      x: this.x,
      y: this.y
    };
  }
}

let shape = new Shape(1, 10, 20);
console.log(`Shape pos:`, JSON.stringify(shape.getPos()));
shape.move(15, 35);
console.log(`Shape pos:`, JSON.stringify(shape.getPos()));
Result
Shape pos: {"x":10,"y":20}
Shape pos: {"x":15,"y":35}

Class Inheritance

More intuitive, OOP-style and boilerplate-free inheritance.

Code
class Rectangle extends Shape {
  constructor(id, x, y, width, height) {
    super(id, x, y);
    this.width = width;
    this.height = height;
  }
  getSize() {
    return {
      width: this.width,
      height: this.height
    };
  }
}

class Circle extends Shape {
  constructor(id, x, y, radius) {
    super(id, x, y);
    this.radius = radius;
  }
}

let rectangle = new Rectangle(2, 11, 21, 100, 200);
console.log(`Rectangle size:`, JSON.stringify(rectangle.getSize()));

let circle = new Circle(2, 80, 90, 50);
console.log(`Circle pos:`, JSON.stringify(circle.getPos()));
Result
Rectangle size: {"width":100,"height":200}
Circle pos: {"x":80,"y":90}

Class Inheritance, From Expressions

Support for mixin-style inheritance by extending from expressions yielding function objects. [Notice: the generic aggregation function is usually provided by a library like this one, of course]

Code
var aggregation = (baseClass, ...mixins) => {
  let base = class _Combined extends baseClass {
    constructor(...args) {
      super(...args);
      mixins.forEach((mixin) => {
        mixin.prototype.initializer.call(this);
      });
    }
  };
  let copyProps = (target, source) => {
    Object.getOwnPropertyNames(source)
      .concat(Object.getOwnPropertySymbols(source))
      .forEach((prop) => {
        if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
          return
        Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
      })
  }
  mixins.forEach((mixin) => {
    copyProps(base.prototype, mixin.prototype);
    copyProps(base, mixin);
  });
  return base;
};

class Colored {
  initializer() {
    this._color = 'white';
  }
  get color() {
    return this._color;
  }
  set color(v) {
    this._color = v;
  }
}

class ZCoord {
  initializer() {
    this._z = 0;
  }
  get z() {
    return this._z;
  }
  set z(v) {
    this._z = v;
  }
}

class Shape {
  constructor(x, y) {
    this._x = x;
    this._y = y;
  }
  get x() {
    return this._x;
  }
  set x(v) {
    this._x = v;
  }
  get y() {
    return this._y;
  }
  set y(v) {
    this._y = v;
  }
}

class Rectangle extends aggregation(Shape, Colored, ZCoord) {}

var rect = new Rectangle(7, 42);
rect.z = 1000;
rect.color = 'red';
console.log(`Rectangle data:
  pos x: ${rect.x}
  pos y: ${rect.y}
  pos z: ${rect.z}
  color: ${rect.color}`);
Result
Rectangle data:
  pos x: 7
  pos y: 42
  pos z: 1000
  color: red

Base Class Access

Intuitive access to base class constructor and methods.

Code
class Shape {
  constructor(id, x, y) {
    this.id = id;
    this.x = x;
    this.y = y;
  }
  toString() {
    return `Shape(${this.id})`;
  }
}
class Rectangle extends Shape {
  constructor(id, x, y, width, height) {
    super(id, x, y);
  }
  toString() {
    return `Rectangle > ${super.toString()}`;
  }
}
class Circle extends Shape {
  constructor(id, x, y, radius) {
    super(id, x, y);
  }
  toString() {
    return `Circle > ${super.toString()}`;
  }
}

let shape = new Shape(1, 10, 20);
console.log(shape.toString());
let rectangle = new Rectangle(2, 20, 30);
console.log(rectangle.toString());
let circle = new Circle(3, 30, 40);
console.log(circle.toString());
Result
Shape(1)
Rectangle > Shape(2)
Circle > Shape(3)

Static Members

Simple support for static class members.

Code
class Rectangle extends Shape {
  constructor(id, x, y, width, height) {
    super(id, x, y);
    this.width = width;
    this.height = height;
  }
  static defaultRectangle() {
    return new Rectangle('default', 2, 2, 100, 100);
  }
}
class Circle extends Shape {
  constructor(id, x, y, radius) {
    super(id, x, y);
    this.radius = radius;
  }
  static defaultCircle() {
    return new Circle('default', 4, 4, 100);
  }
}

let rectangle = Rectangle.defaultRectangle();
console.log(`Rectangle data:`, JSON.stringify(rectangle));
let circle = Circle.defaultCircle();
console.log(`Circle data:`, JSON.stringify(circle));
Result
Rectangle data: {"id":"default","x":2,"y":2,"width":100,"height":100}
Circle data: {"id":"default","x":4,"y":4,"radius":100}

Getter/Setter

Getter/Setter also directly within classes (and not just within object initializers, as it is possible since ECMAScript 5.1).

Code
class Rectangle {
  constructor(width, height) {
    this._width = width;
    this._height = height;
  }
  set width(width) {
    this._width = width;
  }
  get width() {
    return this._width;
  }
  set height(height) {
    this._height = height;
  }
  get height() {
    return this._height;
  }
  get area() {
    return this._width * this._height;
  }
};

var r = new Rectangle(50, 20);
console.log(`Compare rectangle.area === 1000:`, r.area === 1000);
Result
Compare rectangle.area === 1000: true

Symbol Type


Symbol Type

Unique and immutable data type to be used as an identifier for object properties. Symbol can have an optional description, but for debugging purposes only.

Code
console.log(`Symbol("foo"):`, Symbol('foo'));
console.log(`Symbol("foo") !== Symbol("foo"):`, Symbol("foo") !== Symbol("foo"));

const foo = Symbol();
const bar = Symbol();
console.log(`typeof foo === "symbol":`, typeof foo === 'symbol');
console.log(`typeof bar === "symbol":`, typeof bar === 'symbol');

let obj = {};
obj[foo] = "foo";
obj[bar] = "bar";
console.log(`Value obj:`, JSON.stringify(obj));
console.log(`Value Object.keys(obj):`, Object.keys(obj));
console.log(`Value Object.getOwnPropertyNames(obj):`, Object.getOwnPropertyNames(obj));
console.log(`Value Object.getOwnPropertySymbols(obj):`, Object.getOwnPropertySymbols(obj));
console.log(`Value obj["foo"]:`, obj['foo']);
console.log(`Value obj[foo]:`, obj[foo]);
Result
Symbol("foo"): Symbol(foo)
Symbol("foo") !== Symbol("foo"): true
typeof foo === "symbol": true
typeof bar === "symbol": true
Value obj: {}
Value Object.keys(obj): []
Value Object.getOwnPropertyNames(obj): []
Value Object.getOwnPropertySymbols(obj): [Symbol(), Symbol()]
Value obj["foo"]: undefined
Value obj[foo]: foo

Global Symbols

Global symbols, indexed through unique keys.

Code
console.log(`Symbol.for("app.foo") === Symbol.for("app.foo"):`, Symbol.for("app.foo") === Symbol.for("app.foo"));

const foo = Symbol.for("app.foo");
const bar = Symbol.for("app.bar");
console.log(`Symbol.keyFor(foo) === "app.foo":`, Symbol.keyFor(foo) === "app.foo");
console.log(`Symbol.keyFor(bar) === "app.bar":`, Symbol.keyFor(bar) === "app.bar");
console.log(`typeof foo === "symbol":`, typeof foo === "symbol");
console.log(`typeof bar === "symbol":`, typeof bar === "symbol");

let obj = {};
obj[foo] = "foo";
obj[bar] = "bar";
console.log(`Value obj:`, JSON.stringify(obj));
console.log(`Value Object.keys(obj):`, Object.keys(obj));
console.log(`Value Object.getOwnPropertyNames(obj):`, Object.getOwnPropertyNames(obj));
console.log(`Value Object.getOwnPropertySymbols(obj):`, Object.getOwnPropertySymbols(obj));
console.log(`Value obj[foo]:`, obj[foo]);
Result
Symbol.for("app.foo") === Symbol.for("app.foo"): true
Symbol.keyFor(foo) === "app.foo": true
Symbol.keyFor(bar) === "app.bar": true
typeof foo === "symbol": true
typeof bar === "symbol": true
Value obj: {}
Value Object.keys(obj): []
Value Object.getOwnPropertyNames(obj): []
Value Object.getOwnPropertySymbols(obj): [Symbol(app.foo), Symbol(app.bar)]
Value obj[foo]: foo

Iterators


Iterator & For-Of Operator

Support "iterable" protocol to allow objects to customize their iteration behaviour. Additionally, support "iterator" protocol to produce sequence of values (either finite or infinite). Finally, provide convenient of operator to iterate over all values of an iterable object.

Code
let fibonacci = {
  [Symbol.iterator]() {
    let pre = 0,
      cur = 1;
    return {
      next() {
        [pre, cur] = [cur, pre + cur];
        return {
          done: false,
          value: cur
        };
      }
    };
  }
}

for (let n of fibonacci) {
  if (n > 1000)
    break;
  console.log(`Current value fibonacci:`, n);
}
Result
Current value fibonacci: 1
Current value fibonacci: 2
Current value fibonacci: 3
Current value fibonacci: 5
Current value fibonacci: 8
Current value fibonacci: 13
Current value fibonacci: 21
Current value fibonacci: 34
Current value fibonacci: 55
Current value fibonacci: 89
Current value fibonacci: 144
Current value fibonacci: 233
Current value fibonacci: 377
Current value fibonacci: 610
Current value fibonacci: 987

Generators


Generator Function, Iterator Protocol

Support for generators, a special case of Iterators containing a generator function, where the control flow can be paused and resumed, in order to produce sequence of values (either finite or infinite).

Code
let fibonacci = {
  *[Symbol.iterator]() {
    let pre = 0,
      cur = 1;
    for (;;) {
      [pre, cur] = [cur, pre + cur];
      yield cur;
    }
  }
}

for (let n of fibonacci) {
  if (n > 1000)
    break;
  console.log(`Current value fibonacci:`, n);
}
Result
Current value fibonacci: 1
Current value fibonacci: 2
Current value fibonacci: 3
Current value fibonacci: 5
Current value fibonacci: 8
Current value fibonacci: 13
Current value fibonacci: 21
Current value fibonacci: 34
Current value fibonacci: 55
Current value fibonacci: 89
Current value fibonacci: 144
Current value fibonacci: 233
Current value fibonacci: 377
Current value fibonacci: 610
Current value fibonacci: 987

Generator Function, Direct Use

Support for generator functions, a special variant of functions where the control flow can be paused and resumed, in order to produce sequence of values (either finite or infinite).

Code
function* range(start, end, step) {
  while (start < end) {
    yield start;
    start += step;
  }
}

for (let i of range(0, 10, 2)) {
  console.log(`Current value range:`, i);
}
Result
Current value range: 0
Current value range: 2
Current value range: 4
Current value range: 6
Current value range: 8

Generator Matching

Support for generator functions, i.e., functions where the control flow can be paused and resumed, in order to produce and spread sequence of values (either finite or infinite).

Code
let fibonacci = function*(numbers) {
  let pre = 0,
    cur = 1;
  while (numbers-- > 0) {
    [pre, cur] = [cur, pre + cur];
    yield cur;
  }
};

for (let n of fibonacci(10)) {
  console.log(`Current value fibonacci:`, n);
}

let numbers = [...fibonacci(10)];
console.log(`Value numbers:`, JSON.stringify(numbers));
let [n1, n2, n3, ...others] = fibonacci(10);
console.log(`Values n1, n2, n3, others:`, n1, n2, n3, others);
Result
Current value fibonacci: 1
Current value fibonacci: 2
Current value fibonacci: 3
Current value fibonacci: 5
Current value fibonacci: 8
Current value fibonacci: 13
Current value fibonacci: 21
Current value fibonacci: 34
Current value fibonacci: 55
Current value fibonacci: 89
Value numbers: [1,2,3,5,8,13,21,34,55,89]
Values n1, n2, n3, others: 1 2 3 [5, 8, 13, 21, 34, 55, 89]

Generator Control-Flow

Support for generators, a special case of Iterators where the control flow can be paused and resumed, in order to support asynchronous programming in the style of "co-routines" in combination with Promises (see below). [Notice: the generic async function usually is provided by a reusable library and given here just for better understanding. See co or Bluebird's coroutine in practice.]

Code
//  generic asynchronous control-flow driver
function async(proc, ...params) {
  var iterator = proc(...params);
  return new Promise((resolve, reject) => {
    let loop = (value) => {
      let result;
      try {
        result = iterator.next(value);
      } catch (err) {
        reject(err);
      }
      if (result.done)
        resolve(result.value);
      else if (typeof result.value === 'object' &&
        typeof result.value.then === 'function')
        result.value.then((value) => {
          loop(value);
        }, (err) => {
          reject(err);
        });
      else
        loop(result.value);
    }
    loop();
  });
}

//  application-specific asynchronous builder
function makeAsync(text, after) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(text), after);
  });
}

//  application-specific asynchronous procedure
async(function*(greeting) {
  let foo = yield makeAsync('foo', 300)
  let bar = yield makeAsync('bar', 600)
  let baz = yield makeAsync('baz', 100)
  return `${greeting} ${foo} ${bar} ${baz}`
}, 'Hello').then((msg) => {
  console.log(`Result:`, msg);
})
Result
Result: Hello foo bar baz

Generator Methods

Support for generator methods, i.e., methods in classes and on objects, based on generator functions.

Code
class Clz {
  * bar() {
    console.log('Hello bar');
  }
};
let Obj = {
  * foo() {
    console.log('Hello foo');
    yield 1;
    console.log('Bye foo');
    yield 2;
    return "finish!";
  }
};

let clz = new Clz();
console.log(`Clz bar:`, JSON.stringify(clz.bar().next()));

let obj = Obj.foo();
console.log(`Obj.foo:`, JSON.stringify(obj.next()));
console.log(`Obj.foo:`, JSON.stringify(obj.next()));
console.log(`Obj.foo:`, JSON.stringify(obj.next()));
Result
Hello bar
Clz bar: {"done":true}
Hello foo
Obj.foo: {"value":1,"done":false}
Bye foo
Obj.foo: {"value":2,"done":false}
Obj.foo: {"value":"finish!","done":true}

Map/Set & WeakMap/WeakSet


Set Data-Structure

Cleaner data-structure for common algorithms based on sets.

Code
let s = new Set();
s.add('hello').add('goodbye').add('hello');
console.log(`s.size === 2:`, s.size === 2);
console.log(`s.has("hello"):`, s.has('hello') === true);
for (let key of s.values()) {
  console.log(`Data s:`, key);
}
Result
s.size === 2: true
s.has("hello"): true
Data s: hello
Data s: goodbye

Map Data-Structure

Cleaner data-structure for common algorithms based on maps.

Code
let m = new Map();
m.set('hello', 42);
m.set(s, 34);
console.log(`m.get(s) === 34:`, m.get(s) === 34);
console.log(`m.size === 2:`, m.size === 2);
for (let [key, val] of m.entries()) {
  console.log(`key:`, key, ` - val:`, val);
}
Result
m.get(s) === 34: true
m.size === 2: true
key: hello  - val: 42
key: Set(2) {"hello", "goodbye"}  - val: 34


Typed Arrays


Typed Arrays

Support for arbitrary byte-based data structures to implement network protocols, cryptography algorithms, file format manipulations, etc.

Code
//  ES6 class equivalent to the following C structure:
//  struct Example { unsigned long id; char username[16]; float amountDue; };
class Example {
  constructor(buffer = new ArrayBuffer(24)) {
    this.buffer = buffer;
  }
  set buffer(buffer) {
    this._buffer = buffer;
    this._id = new Uint32Array(this._buffer, 0, 1);
    this._username = new Uint8Array(this._buffer, 4, 16);
    this._amountDue = new Float32Array(this._buffer, 20, 1);
  }
  get buffer() {
    return this._buffer;
  }
  set id(v) {
    this._id[0] = v;
  }
  get id() {
    return this._id[0];
  }
  set username(v) {
    this._username[0] = v;
  }
  get username() {
    return this._username[0];
  }
  set amountDue(v) {
    this._amountDue[0] = v;
  }
  get amountDue() {
    return this._amountDue[0];
  }
}

let example = new Example();
example.id = 7;
example.username = "John Doe";
example.amountDue = 42.0;

console.log(`Value example.id:`, example.id);
console.log(`Value example.username:`, example.username);
console.log(`Value example.amountDue:`, example.amountDue);
Result
Value example.id: 7
Value example.username: 0
Value example.amountDue: 42

New Built-In Methods


Object Property Assignment

New function for assigning enumerable properties of one or more source objects onto a destination object.

Code
var dst = {
  quux: 0
};
var src1 = {
  foo: 1,
  bar: 2
};
var src2 = {
  foo: 3,
  baz: 4
};
Object.assign(dst, src1, src2);
console.log(`Value dst.quux:`, dst.quux);
console.log(`Value dst.foo:`, dst.foo);
console.log(`Value dst.bar:`, dst.bar);
console.log(`Value dst.baz:`, dst.baz);
Result
Value dst.quux: 0
Value dst.foo: 3
Value dst.bar: 2
Value dst.baz: 4

Array Element Finding

New function for finding an element in an array.

Code
let find = [1, 3, 4, 2].find(x => x > 3);
console.log(`Find value x > 3:`, find);
Result
Find value x > 3: 4

String Repeating

New string repeating functionality.

Code
let repeat1 = ' '.repeat(4 * 2);
let repeat2 = 'foo'.repeat(3);
console.log(`' '.repeat(4 * 2):`, repeat1);
console.log(`'foo'.repeat(3):`, repeat2);
Result
' '.repeat(4 * 2):
new_built_in_methods.js:44 'foo'.repeat(3): foofoofoo

String Searching

New specific string functions to search for a sub-string.

Code
console.log(`'hello'.startsWith('ello', 1):`, 'hello'.startsWith('ello', 1));
console.log(`'hello'.endsWith('hell', 4):`, 'hello'.endsWith('hell', 4));
console.log(`'hello'.includes('ell'):`, 'hello'.includes('ell'));
console.log(`'hello'.includes('ell', 1):`, 'hello'.includes('ell', 1));
console.log(`'hello'.includes('ell', 2):`, 'hello'.includes('ell', 2));
Result
'hello'.startsWith('ello', 1): true
'hello'.endsWith('hell', 4): true
'hello'.includes('ell'): true
'hello'.includes('ell', 1): true
'hello'.includes('ell', 2): false

Number Type Checking

New functions for checking for non-numbers and finite numbers.

Code
console.log(`Number.isNaN(42):`, Number.isNaN(42));
console.log(`Number.isNaN(NaN):`, Number.isNaN(NaN));
console.log(`Number.isFinite(Infinity):`, Number.isFinite(Infinity));
console.log(`Number.isFinite(-Infinity):`, Number.isFinite(-Infinity));
console.log(`Number.isFinite(NaN):`, Number.isFinite(NaN));
console.log(`Number.isFinite(123):`, Number.isFinite(123));
Result
Number.isNaN(42): false
Number.isNaN(NaN): true
Number.isFinite(Infinity): false
Number.isFinite(-Infinity): false
Number.isFinite(NaN): false
Number.isFinite(123): true

Number Safety Checking

Checking whether an integer number is in the safe range, i.e., it is correctly represented by JavaScript (where all numbers, including integer numbers, are technically floating point number).

Code
let isSafety1 = Number.isSafeInteger(42);
let isSafety2 = Number.isSafeInteger(9007199254740992);
console.log(`Number.isSafeInteger(42):`, isSafety1);
console.log(`Number.isSafeInteger(9007199254740992):`, isSafety2);
Result
Number.isSafeInteger(42): true
Number.isSafeInteger(9007199254740992): false

Number Comparison

Availability of a standard Epsilon value for more precise comparison of floating point numbers.

Code
let num_comp1 = (0.1 + 0.2 === 0.3);
let num_comp2 = (Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON);
console.log(`0.1 + 0.2 === 0.3:`, num_comp1);
console.log(`Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON:`, num_comp2);
Result
0.1 + 0.2 === 0.3: false
Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON: true

Number Truncation

Truncate a floating point number to its integral part, completely dropping the fractional part.

Code
console.log(`Math.trunc(42.7):`, Math.trunc(42.7));
console.log(`Math.trunc( 0.1):`, Math.trunc(0.1));
console.log(`Math.trunc(-0.1):`, Math.trunc(-0.1));
Result
Math.trunc(42.7): 42
Math.trunc( 0.1): 0
Math.trunc(-0.1): -0

Number Sign Determination

Determine the sign of a number, including special cases of signed zero and non-number.

Code
console.log(`Math.sign(7):`, Math.sign(7));
console.log(`Math.sign(0):`, Math.sign(0));
console.log(`Math.sign(-0):`, Math.sign(-0));
console.log(`Math.sign(-7):`, Math.sign(-7));
console.log(`Math.sign(NaN):`, Math.sign(NaN));
Result
Math.sign(7): 1
Math.sign(0): 0
Math.sign(-0): -0
Math.sign(-7): -1
Math.sign(NaN): NaN

Promises


Promise Usage

First class representation of a value that may be made asynchronously and be available in the future.

Code
function msgAfterTimeout(msg, who, timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(`${msg} Hello ${who}!`), timeout);
  });
}

msgAfterTimeout('', 'Foo', 100).then((msg) =>
  msgAfterTimeout(msg, 'Bar', 200)
).then((msg) => {
  console.log(`Response promise after 300ms:`, msg);
});
Result
Response promise after 300ms:  Hello Foo! Hello Bar!

Promise Combination

Combine one or more promises into new promises without having to take care of ordering of the underlying asynchronous operations yourself.

Code
let fetchPromised = (name, timeout) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(`Hi ${name}`), timeout);
  });
}

Promise.all([
  fetchPromised('Foo', 1000),
  fetchPromised('Bar', 500),
  fetchPromised('Baz', 200)
]).then((data) => {
  let [foo, bar, baz] = data;
  console.log(`Response all promises: foo=${foo} bar=${bar} baz=${baz}`);
}, (err) => {
  console.log(`Error: ${err}`);
});
Result
Response all promises: foo=Hi Foo bar=Hi Bar baz=Hi Baz

Meta-Programming


Proxying

Hooking into runtime-level object meta-operations.

Code
let target = {
  foo: 'Welcome, foo'
};
let proxy = new Proxy(target, {
  get(receiver, name) {
        return name in receiver ? receiver[name] : `Hello, ${name}`;
  }
});
console.log(`proxy.foo:`, proxy.foo);
console.log(`proxy.world:`, proxy.world);
Result
proxy.foo: Welcome, foo
proxy.world: Hello, world

Reflection

Make calls corresponding to the object meta-operations.

Code
let obj = {
  a: 1
};
Object.defineProperty(obj, "b", {
  value: 2
});
obj[Symbol("c")] = 3;
console.log(`Reflect.ownKeys(obj):`, Reflect.ownKeys(obj));
Result
Reflect.ownKeys(obj): ["a", "b", Symbol(c)]

Internationalization & Localization


Collation

Sorting a set of strings and searching within a set of strings. Collation is parameterized by locale and aware of Unicode.

Code
// in German,  'ä' sorts with 'a'
// in Swedish, 'ä' sorts after 'z'
let list = ['ä', 'a', 'z'];
let l10nDE = new Intl.Collator('de');
let l10nSV = new Intl.Collator('sv');
console.log(`l10nDE.compare('ä', 'z'):`, l10nDE.compare('ä', 'z'));
console.log(`l10nSV.compare('ä', 'z'):`, l10nSV.compare('ä', 'z'));
console.log(`list.sort(l10nDE.compare):`, list.sort(l10nDE.compare));
console.log(`list.sort(l10nSV.compare):`, list.sort(l10nSV.compare));
Result
l10nDE.compare('ä', 'z'): -1
l10nSV.compare('ä', 'z'): 1
list.sort(l10nDE.compare): ["a", "ä", "z"]
list.sort(l10nSV.compare): ["a", "z", "ä"]

Number Formatting

Format numbers with digit grouping and localized separators.

Code
let l10nEN = new Intl.NumberFormat('en-US');
let l10nDE = new Intl.NumberFormat('de-DE');
console.log(`Compare number format EN:`, l10nEN.format(1234567.89) === '1,234,567.89');
console.log(`Compare number format DE:`, l10nDE.format(1234567.89) === '1.234.567,89');
Result
Compare number format EN: true
Compare number format DE: true

Currency Formatting

Format numbers with digit grouping, localized separators and attached currency symbol.

Code
let l10nUSD = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});
let l10nGBP = new Intl.NumberFormat('en-GB', {
  style: 'currency',
  currency: 'GBP'
});
let l10nEUR = new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
});
console.log(`Compare currency format USD:`, l10nUSD.format(100200300.40) === '$100,200,300.40');
console.log(`Compare currency format GBP:`, l10nGBP.format(100200300.40) === '£100,200,300.40');
console.log(`Compare currency format EUR:`, l10nEUR.format(100200300.40) === '100.200.300,40 €');
Result
Compare currency format USD: true
Compare currency format GBP: true
Compare currency format EUR: true

Date/Time Formatting

Format date/time with localized ordering and separators.

Code
let l10nEN = new Intl.DateTimeFormat('en-US');
let l10nDE = new Intl.DateTimeFormat('de-DE');
console.log(`Compare date format EN:`, l10nEN.format(new Date('2017-01-02')) === '1/2/2017');
console.log(`Compare date format DE:`, l10nDE.format(new Date('2017-01-02')) === '2.1.2017');
Result
Compare date format EN: true
Compare date format DE: true