ecmascript

Documentation of Meteor's ecmascript package.

This package lets you use new JavaScript language features that are partof the ECMAScript 2015specification but arenot yet supported by all engines or browsers. Unsupported syntax isautomatically translated into standard JavaScript that behaves the sameway.

This video from the July2015 Meteor Devshop gives an overview of how the package works, and whatit provides.

Usage

The ecmascript package registers a compiler plugin that transpilesECMAScript 2015+ to ECMAScript 5 (standard JS) in all .js files. Bydefault, this package is pre-installed for all new apps and packages.

To add this package to an existing app, run the following command fromyour app directory:

  1. meteor add ecmascript

To add the ecmascript package to an existing package, include thestatement api.use('ecmascript'); in the Package.onUse callback in yourpackage.js file:

  1. Package.onUse((api) => {
  2. api.use('ecmascript');
  3. });

Supported ES2015 Features

Syntax

The ecmascript package uses Babel to compileES2015 syntax to ES5 syntax. Many but not all ES2015 features can besimulated by Babel, and ecmascript enables most of the featuressupported by Babel.

Here is a list of the Babel transformers that are currently enabled:

  • es3.propertyLiteralsMakes it safe to use reserved keywords like catch as unquoted keys inobject literals. For example, { catch: 123 } is translated to { "catch": 123 }.

  • es3.memberExpressionLiteralsMakes it safe to use reserved keywords as property names. Forexample, object.catch is translated to object["catch"].

  • es6.arrowFunctionsProvides a shorthand for function expressions. For example,[1, 2, 3].map(x => x + 1) evaluates to [2, 3, 4]. If this is usedin the body of the arrow function, it will be automatically bound to thevalue of this in the enclosing scope.

  • es6.literalsAdds support for binary and octal numeric literals. For example,0b111110111 === 503 and 0o767 === 503.

  • es6.templateLiteralsEnables multi-line strings delimited by backticks instead of quotationmarks, with variable interpolation:

  1. var name = 'Ben';
  2. var message = `My name is:
  3. ${name}`;
  1. class Base {
  2. constructor(a, b) {
  3. this.value = a * b;
  4. }
  5. }
  6. class Derived extends Base {
  7. constructor(a, b) {
  8. super(a + 1, b + 1);
  9. }
  10. }
  11. var d = new Derived(2, 3);
  12. d.value; // 12
  • es6.constantsAllows defining block-scoped variables that are not allowed to beredefined:
  1. const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;
  2. // This reassignment will be forbidden by the compiler:
  3. GOLDEN_RATIO = 'new value';
  • es6.blockScopingEnables the let and const keywords as alternatives to var. The keydifference is that variables defined using let or const arevisible only within the block where they are declared, rather than beingvisible anywhere in the enclosing function. For example:
  1. function example(condition) {
  2. let x = 0;
  3. if (condition) {
  4. let x = 1;
  5. console.log(x);
  6. } else {
  7. console.log(x);
  8. x = 2;
  9. }
  10. return x;
  11. }
  12. example(true); // logs 1, returns 0
  13. example(false); // logs 0, returns 2
  • es6.properties.shorthandAllows omitting the value of an object literal property when the desiredvalue is held by a variable that has the same name as the propertykey. For example, instead of writing { x: x, y: y, z: "asdf" } you canjust write { x, y, z: "asdf" }. Methods can also be written withoutthe : function property syntax:
  1. var obj = {
  2. oldWay: function (a, b) { ... },
  3. newWay(a, b) { ... }
  4. };
  1. var counter = 0;
  2. function getKeyName() {
  3. return 'key' + counter++;
  4. }
  5. var obj = {
  6. [getKeyName()]: 'zero',
  7. [getKeyName()]: 'one',
  8. };
  9. obj.key0; // 'zero'
  10. obj.key1; // 'one'
  • es6.parametersDefault expressions for function parameters, evaluated whenever the parameteris undefined, …rest parameters for capturing remainingarguments without using the arguments object:
  1. function add(a = 0, ...rest) {
  2. rest.forEach(n => a += n);
  3. return a;
  4. }
  5. add(); // 0
  6. add(1, 2, 3); // 6
  • es6.spreadAllows an array of arguments to be interpolated into a list of argumentsto a function call, new expression, or array literal, without usingFunction.prototype.apply:
  1. add(1, ...[2, 3, 4], 5); // 15
  2. new Node('name', ...children);
  3. [1, ...[2, 3, 4], 5]; // [1, 2, 3, 4, 5]
  • es6.forOfProvides an easy way to iterate over the elements of a collection:
  1. let sum = 0;
  2. for (var x of [1, 2, 3]) {
  3. sum += x;
  4. }
  5. sum; // 6
  • es6.destructuringDestructuring is the technique of using an array or object pattern onthe left-hand side of an assignment or declaration, in place of theusual variable or parameter, so that certain sub-properties of the valueon the right-hand side will be bound to identifiers that appear within thepattern. Perhaps the simplest example is swapping two variables withoutusing a temporary variable:
  1. [a, b] = [b, a];

Extracting a specific property from an object:

  1. let { username: name } = user;
  2. // is equivalent to
  3. let name = user.username;

Instead of taking a single opaque options parameter, a function canuse an object destructuring pattern to name the expected options:

  1. function run({ command, args, callback }) { ... }
  2. run({
  3. command: 'git',
  4. args: ['status', '.'],
  5. callback(error, status) { ... },
  6. unused: 'whatever'
  7. });
  • es7.objectRestSpreadSupports catch-all …rest properties in object literal declarationsand assignments:
  1. let { x, y, ...rest } = { x: 1, y: 2, a: 3, b: 4 };
  2. x; // 1
  3. y; // 2
  4. rest; // { a: 3, b: 4 }

Also enables …spread properties in object literal expressions:

  1. let n = { x, y, ...rest };
  2. n; // { x: 1, y: 2, a: 3, b: 4 }
  • es7.trailingFunctionCommasAllows the final parameter of a function to be followed by a comma,provided that parameter is not a …rest parameter.

  • flowPermits the use of Flow type annotations. Theseannotations are simply stripped from the code, so they have no effect onthe code’s behavior, but you can run the flow tool over your code tocheck the types if desired.

Polyfills

The ECMAScript 2015 standard library has grown to include new APIs anddata structures, some of which can be implemented (“polyfilled”) usingJavaScript that runs in all engines and browsers today. Here are three newconstructors that are guaranteed to be available when the ecmascriptpackage is installed:

  • PromiseA Promise allows its owner to wait for a value that might not beavailable yet. See this tutorial for moredetails about the API and motivation. The Meteor Promiseimplementation is especially useful because it runs all callbackfunctions in recycled Fibers, so you can use any Meteor API, includingthose that yield (e.g. HTTP.get, Meteor.call, or MongoCollection),and you never have to call Meteor.bindEnvironment.

  • MapAn associative key-value data structure where the keys can be anyJavaScript value (not just strings). Lookup and insertion take constanttime.

  • SetA collection of unique JavaScript values of any type. Lookup andinsertion take constant time.

  • SymbolAn implementation of the globalSymbols namespacethat enables a number of other ES2015 features, such as for-of loopsand Symbol.iterator methods: [1,2,3]Symbol.iterator.

  • Polyfills for the following Object-related methods:

    • Object.assign
    • Object.is
    • Object.setPrototypeOf
    • Object.prototype.toString (fixes @@toStringTag support)Complete reference here.
  • Polyfills for the following String-related methods:

    • String.fromCodePoint
    • String.raw
    • String.prototype.includes
    • String.prototype.startsWith
    • String.prototype.endsWith
    • String.prototype.repeat
    • String.prototype.codePointAt
    • String.prototype.trimComplete reference here.
  • Polyfills for the following Array-related methods:

    • Array.from
    • Array.of
    • Array.prototype.copyWithin
    • Array.prototype.fill
    • Array.prototype.find
    • Array.prototype.findIndexComplete reference here.
  • Polyfills for the following Function-related properties:

    • Function.prototype.name (fixes IE9+)
    • Function.prototype[Symbol.hasInstance] (fixes IE9+)Complete reference here.