Export Default Sugarings
Good observation. However, if I were to simplify, I’d only keep #3. #1 and #2 look more syntactically questionable to me (kind of abusing names as keywords/markers).
Good observation. However, if I were to simplify, I’d only keep #3. #1 and #2 look more syntactically questionable to me (kind of abusing names as keywords/markers).
#1 is the base case because it is completely general. Any IdentifierName may appear in the "as" clause.
export { x as delete, y as new, z as default }; // Perfectly fine!
Of course, "default" has special meaning on the import side:
import x from "package:foo";
Desugars (very beautifully) to:
import { default as x } from "package:foo";
The sugaring on the import side is a clear win, but I'm not so sure about the sugarings on the export side.
#2 was removed at the hallway discussion of the face to face meeting. Do you still think we should remove #3?
My only real issue with #3 is that it raises a footgun flag for me:
export default function parse1JS(code) {
// ...
}
parse1JS.foo = "bar"; // Surprise! [ReferenceError: parse1JS" is not defined]
It's an assignment, but it looks like a declaration. Being an assignment, you need the "=" to signal to the user that what follows is an expression:
export default = function parse1JS(code) { }; // Obviously an expression!
On 5 December 2013 16:48, Kevin Smith <zenparsing at gmail.com> wrote:
#1 is the base case because it is completely general. Any IdentifierName may appear in the "as" clause.
export { x as delete, y as new, z as default }; // Perfectly fine! ```
I certainly wouldn't mind this simplification either.
Of course, "default" has special meaning on the import side:
import x from "package:foo"; Desugars (very beautifully) to: ```js import { default as x } from "package:foo";
The sugaring on the import side is a clear win, but I'm not so sure about the sugarings on the export side.
Although the import side has this one extra syntactic special case for defaults:
import x, {y as z, ...} from "..."
That seems really redundant. I assume mixing default import with others will be an extremely rare case, and when really needed, can easily be expressed as either
import {default as x, y as z, ...} from "..."
or
import x from "..."
import {y as z, ...} from "..."
I didn't even realize that was allowed, and I agree with you completely.
The import crazy, {more as boo} from 'name'
needs to go away.
It is also bad because the order there is fixed and you cannot interleave.
#2 was removed at the hallway discussion of the face to face meeting. Do you still think we should remove #3?
After thinking about it a little more, I think deferring #3 might be best
after all. Let's assume that the syntax is export default = AssignmentExpression
. And further, let's assume that when a default
export is specified, it will almost invariably be a function or class. If
so, then #3 will almost always be inferior to #1.
Consider the following module cycle, where the modules are arranged in their execution order:
// A.js
import b from "B.js";
b(); // Error: b has not been initialized
// B.js
import {} from "A.js";
function b() {}
export default = b;
// main.js
import {} from "B.js";
I believe that this will fail, because the local binding "b" in "A.js" has not been initialized yet. However, using #1 it works just fine:
// A.js
import b from "B.js";
b(); // OK
// B.js
import {} from "A.js";
function b() {}
export { b as default };
// main.js
import {} from "B.js";
The aesthetic advantage of #3 over #1 is arguable at best, so it appears that the only way in which #3 is justified is when the exported value is actually constructed at runtime. At this time, it's not clear to me that this is anything but a rare edge case. If ES6 usage patterns prove otherwise, then a case can be built for adding syntax in ES7.
Thanks for hearing me out!
TLDR: We should consider deferring specialized syntax for exporting a "default" binding until after ES6.
In the current draft, there are 3 ways to export a default binding:
Export a local binding with the name "default":
class Parser { ... } export { Parser as default };
Use "default" as a BindingIdentifier. BindingIdentifer is parameterized on [Default]:
export class default { ... }
Use a "default" assignment:
export default class { ... }; // AssignmentExpression
Methods 2 and 3 are inessential - they can be expressed in terms of 1.
Methods 2 and 3 are minor optimizations. Method 1 is by no means painful to write or read.
There are some potential downsides to providing methods 2 and 3:
Proposal: defer "default export" sugarings until ES7, when we can use data gathered from experience with ES6 modules to guide syntax additions.