`export { foo as default }` 是否有效 ES2015?

Is `export { foo as default }` valid ES2015?

我收到了一个关于我的 ES2015 模块 import/export 的 ESLint 验证插件的 issue on GitHub 无法识别 default 导出的以下语法:

export { 
    foo as default,
    bar
}

我的插件将在哪里检查以下(等效?)语法没问题:

export default foo;
export const bar = ..;

两者 Babel and Esprima 都能正确解析相似的语法,这适用于两端使用 Babel 的代码(导入和导出)。

但是,我不相信 spec 允许前一种 export { x as default } 形式:

For each IdentifierName n in ReferencedBindings of ExportClause : It is a Syntax Error if StringValue of n is a ReservedWord or if the StringValue of n is one of: "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield".

ReservedWord does include default, though I think one could argue that ReferencedBindings is referring specifically to the module-local identifier names 正在 导出 (即 foo),而不是导出的名称本身。

能够导出保留字通常看起来也很奇怪; Babel 也很乐意允许像

这样的东西
// ./foo.js
export { foo as yield }
// ./mod.js
import { yield as nonReservedIdentifier } from './foo'

因此,总结一下:export { foo as default } 是在 ES2015 中导出默认值的有效方法吗?

是的,ReferencedBindings 仅指第一个 IdentifierName。所以

export { default as something } // or
export { default }

无效,但是

export { something as default }

不是。 ESLint 需要在这里进行修复。

是的,有效。我来分解一下。

  1. :

    export { foo as default }
    

    这与以下产品相匹配(从最不具体到最具体):

    export ExportClause
    ExportClause : { ExportsList }
    ExportsList : ExportSpecifier
    ExportSpecifier : IdentifierName as IdentifierName    
    
  2. 那么你有 early error semantics:

    15.2.3.1 Static Semantics: Early Errors

    ExportDeclaration : export ExportClause ;

    For each IdentifierName n in ReferencedBindings of ExportClause : It is a Syntax Error if StringValue of n is a ReservedWord...

    这些适用于匹配 export ExportClause 的任何作品,包括您的示例语法。这将调用 ReferencedBindings 算法。

  3. 适用于与此语法匹配的最具体产生式的ReferencedBindings算法是:

    ExportSpecifier : IdentifierName as IdentifierName

    Return a List containing the first IdentifierName.

因此您看到关于 ReservedWord 和其他列出的值的限制仅适用于示例中语法的 foo 部分。