跳至内容

ECMAScript

此包允许您使用新的 JavaScript 语言特性,这些特性是 ECMAScript 2015 规范 的一部分,但尚未被所有引擎或浏览器支持。不支持的语法会自动转换为行为相同的标准 JavaScript。

此视频 来自 2015 年 7 月的 Meteor Devshop,概述了该包的工作原理及其提供的功能。

用法

ecmascript 包注册了一个编译器插件,该插件会将 ECMAScript 2015+ 转换为 ECMAScript 5(标准 JS)在所有 .js 文件中。默认情况下,此包已预安装到所有新的应用程序和包中。

要将此包添加到现有应用程序中,请从您的应用程序目录运行以下命令

bash
meteor add ecmascript

要将 ecmascript 包添加到现有包中,请在 package.js 文件中的 Package.onUse 回调中包含语句 api.use('ecmascript');

js
Package.onUse((api) => {
  api.use('ecmascript');
});

支持的 ES2015 特性

语法

ecmascript 包使用 Babel 将 ES2015 语法编译为 ES5 语法。Babel 可以模拟许多(但不是全部)ES2015 特性,而 ecmascript 启用了 Babel 支持的大多数特性。

以下是当前启用的 Babel 变换器列表

  • es3.propertyLiterals
    可以安全地使用保留关键字(如 catch)作为对象字面量中的未加引号的键。例如,{ catch: 123 } 将转换为 { "catch": 123 }

  • es3.memberExpressionLiterals
    可以安全地使用保留关键字作为属性名称。例如,object.catch 将转换为 object["catch"]

  • es6.arrowFunctions
    为函数表达式提供简写。例如,[1, 2, 3].map(x => x + 1) 计算结果为 [2, 3, 4]。如果在箭头函数的主体中使用了 this,它将自动绑定到封闭作用域中 this 的值。

  • es6.literals
    添加对二进制和八进制数字字面量的支持。例如,0b111110111 === 5030o767 === 503

  • es6.templateLiterals
    启用由反引号而不是引号分隔的多行字符串,并进行变量插值

    js
    var name = 'Ben';
    var message = `My name is:
    ${name}`;
  • es6.classes
    启用 class 语法

    js
    class Base {
      constructor(a, b) {
        this.value = a * b;
      }
    }
    
    class Derived extends Base {
      constructor(a, b) {
        super(a + 1, b + 1);
      }
    }
    
    var d = new Derived(2, 3);
    d.value; // 12
  • es6.constants
    允许定义不允许重新定义的块作用域变量

    js
    const GOLDEN_RATIO = (1 + Math.sqrt(5)) / 2;
    
    // This reassignment will be forbidden by the compiler:
    GOLDEN_RATIO = 'new value';
  • es6.blockScoping
    启用 letconst 关键字作为 var 的替代方案。关键区别在于,使用 letconst 定义的变量仅在其声明的块内可见,而不是在其封闭函数中的任何地方可见。例如

    js
    function example(condition) {
      let x = 0;
      if (condition) {
        let x = 1;
        console.log(x);
      } else {
        console.log(x);
        x = 2;
      }
      return x;
    }
    
    example(true); // logs 1, returns 0
    example(false); // logs 0, returns 2
  • es6.properties.shorthand
    当所需的值由与属性键同名的变量保存时,允许省略对象字面量属性的值。例如,您可以只写 { x, y, z: "asdf" },而不是写 { x: x, y: y, z: "asdf" }。方法也可以在没有 : function 属性语法的情况下编写

    js
    var obj = {
      oldWay: function (a, b) { ... },
      newWay(a, b) { ... }
    };
  • es6.properties.computed
    允许具有动态计算键的对象字面量属性

    js
    var counter = 0;
    function getKeyName() {
      return 'key' + counter++;
    }
    
    var obj = {
      [getKeyName()]: 'zero',
      [getKeyName()]: 'one',
    };
    
    obj.key0; // 'zero'
    obj.key1; // 'one'
  • es6.parameters
    函数参数的默认表达式,在参数为 undefined 时进行评估,...rest 参数用于捕获剩余参数,而不使用 arguments 对象

    js
    function add(a = 0, ...rest) {
      rest.forEach(n => a += n);
      return a;
    }
    
    add(); // 0
    add(1, 2, 3); // 6
  • es6.spread
    允许将参数数组插值到函数调用、new 表达式或数组字面量的参数列表中,而不使用 Function.prototype.apply

    js
    add(1, ...[2, 3, 4], 5); // 15
    new Node('name', ...children);
    [1, ...[2, 3, 4], 5]; // [1, 2, 3, 4, 5]
  • es6.forOf
    提供了一种简单的方法来迭代集合的元素

    js
    let sum = 0;
    for (var x of [1, 2, 3]) {
      sum += x;
    }
    sum; // 6
  • es6.destructuring
    解构是在赋值或声明的左侧使用数组或对象模式的技术,而不是通常的变量或参数,以便右侧值的某些子属性将绑定到模式中出现的标识符。也许最简单的例子是在不使用临时变量的情况下交换两个变量

    js
    [a, b] = [b, a];

    从对象中提取特定属性

    js
    let { username: name } = user;
    // is equivalent to
    let name = user.username;

    函数可以使用对象解构模式为预期的选项命名,而不是采用单个不透明的 options 参数

    js
    function run({ command, args, callback }) { ... }
    
    run({
      command: 'git',
      args: ['status', '.'],
      callback(error, status) { ... },
      unused: 'whatever'
    });
  • es7.objectRestSpread
    支持对象字面量声明和赋值中的 catch-all ...rest 属性

    js
    let { x, y, ...rest } = { x: 1, y: 2, a: 3, b: 4 };
    x; // 1
    y; // 2
    rest; // { a: 3, b: 4 }

    还在对象字面量表达式中启用 ...spread 属性

    js
    let n = { x, y, ...rest };
    n; // { x: 1, y: 2, a: 3, b: 4 }
  • es7.trailingFunctionCommas
    允许函数的最后一个参数后跟逗号,前提是该参数不是 ...rest 参数。

  • flow
    允许使用 Flow 类型注释。这些注释只是从代码中剥离,因此不会影响代码的行为,但如果需要,您可以对代码运行 flow 工具以检查类型。

Polyfills

ECMAScript 2015 标准库已发展到包括新的 API 和数据结构,其中一些可以使用在当今所有引擎和浏览器中运行的 JavaScript 来实现(“polyfill”)。以下是安装 ecmascript 包后保证可用的三个新构造函数

  • Promise
    Promise 允许其所有者等待可能尚未可用的值。有关 API 和动机的更多详细信息,请参阅 本教程。Meteor Promise 实现特别有用,因为它在回收的 Fiber 中运行所有回调函数,因此您可以使用任何 Meteor API,包括那些会产生 yield 的 API(例如 HTTP.getMeteor.callMongoCollection),并且您永远不必调用 Meteor.bindEnvironment

  • Map
    一个关联的键值数据结构,其中键可以是任何 JavaScript 值(不仅仅是字符串)。查找和插入需要恒定时间。

  • Set
    任何类型的唯一 JavaScript 值的集合。查找和插入需要恒定时间。

  • Symbol
    全局 Symbols 命名空间的实现,它启用了许多其他 ES2015 特性,例如 for-of 循环和 Symbol.iterator 方法:[1,2,3][Symbol.iterator]()

  • 以下 Object 相关方法的 Polyfills

    • Object.assign
    • Object.is
    • Object.setPrototypeOf
    • Object.prototype.toString(修复 @@toStringTag 支持)

    完整参考 此处

  • 以下 String 相关方法的 Polyfills

    • String.fromCodePoint
    • String.raw
    • String.prototype.includes
    • String.prototype.startsWith
    • String.prototype.endsWith
    • String.prototype.repeat
    • String.prototype.codePointAt
    • String.prototype.trim

    完整参考 此处

  • 以下 Array 相关方法的 Polyfills

    • Array.from
    • Array.of
    • Array.prototype.copyWithin
    • Array.prototype.fill
    • Array.prototype.find
    • Array.prototype.findIndex

    完整参考 此处

  • 以下 Function 相关属性的 Polyfills

    • Function.prototype.name(修复 IE9+)
    • Function.prototype[Symbol.hasInstance](修复 IE9+)

    完整参考 此处