ES6 already has what you want: _Named Exports_:
export var foo = 1; _Single Export Object_: export var moduleName = { foo: 1, bar: function() {} }; _Single Export Function_: export function fName() { } And even cooler, the syntax for import is uniform, import {foo} from './namedExport'; import {moduleName} from './singleExportObject'; import {fName} from './singleExportFunction'; On Fri, Jun 20, 2014 at 3:21 PM, Ron Buckton <rbuck...@chronicles.org> wrote: > > -----Original Message----- > > > From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of > > > Sébastien Cevey > > > Sent: Friday, June 20, 2014 3:46 AM > > > To: Axel Rauschmayer > > > Cc: es-discuss list > > > Subject: Re: ModuleImport > > > > > > On 20 June 2014 11:39, Axel Rauschmayer <a...@rauschma.de> wrote: > > > > > The `*' symbol universally represents a glob of "everything", but > > > > > when used to import from a module that has multiple exports, you > > > > > won't get everything, you will get either the single default export > > > > > (if there is > > > > > one) or nothing. > > > > > > > > > > > > What gives you that impression? Quoting David’s original email: > > > > > > > > ```js > > > > import * as fs from "fs"; // importing the named exports as an object > > > > import Dict from "dict"; // importing a default export, same as ever > > > > ``` > > > > With all due respect, why is it that we cannot change the specification to > allow `import name from "module"` for both the default export (for single > export modules) and the Module object (for multi-named export modules). The > same question goes for using `import { name as "name" } from "module"` for > both. As specified, a default export is equivalent to a Module object with > a "default" property, and as a result requires special handling with > respect to how it is bound to the _ImportBinding_ in `import name from > "module"`. Wouldn't it make sense to simplify the syntax and expand the > static and runtime semantics for imports? Are we sure that the current > semantics are the right approach that we should shoehorn the syntax into? > > > > > Is it imperative for module authors to be able to provide both a default > export *and* named exports within the same module? From most of the > comments in this thread, it seems that expected module use falls into two > categories: Single-export modules and Multi-export modules. Is there a > use-case in the wild (via ES6 module transpilers) where a single module > today uses both a default export as well as named exports? > > > > With respect to Node libraries, I often see one of three approaches to > exporting from a module: > > > > _Named Exports_: > > ``` > > exports.foo = 1; > > // or > > module.exports.foo = 1; > > ``` > > > > _Single Export Object_: > > ``` > > module.exports = { > > foo: 1, > > bar: function() {} > } > > ``` > > > > _Single Export Function_: > > ``` > > module.exports = function() { } > > ``` > > > > In Node, if you wanted to have a default export that is a function, but > also have additional exports you would most likely add them as data > properties on the function: > > ``` > > module.exports = function() {} > > module.exports.foo = 1; > > ``` > > > > Given that, why not simplify the syntax and semantics to just the > following three forms: > > ``` > > import "module"; // imports the module but does not perform binding > > import name from "module"; // imports the module (either the default > export or a module object with the named exports, see below) > > import { name1, name2 as "otherName" } from "module"; // imports members > of the module. > > ``` > > > > Simplifying this requires the following (approximate) changes in semantics: > > > > * Either (A) a module cannot have *both* a default export and named > exports, _or_.. > > * (B) A modules named exports become attached properties of the default > export if provided. > > * If (B), it becomes an runtime error to add a default export after a > named export, and a runtime error to add a named export if the default > export is not an Object. > > * The ImportBinding (`name` above) becomes bound to a [[Value]] property > of an (not part of the current spec) Import exotic object. > > * When the Module exotic object is loaded, if it has a property named > "default", that becomes the value of the [[Value]] property of the Import > exotic object. > > * If the Module exotic object does not have a property named "default", > the Module itself becomes the value of the [[Value]] property of the Import > exotic object. > > * NamedImports now points to bindings to the [[Value]] property of the > Import exotic object. If you want both a default export and named exports, > attach the named exports as properties of the default export. > > > > With the above changes, whether you're using a default export or named > exports becomes transparent to the developer. If the developer _really_ > wants the module object, they could fall back to: > > ``` > > import "module"; > > var name = System.get("module"); // Returns the Module object without the > transformations applied from above. > > ``` > > > > The above is a rough approximation of the semantics changes. If anyone > finds merit to this proposal, I'll find some time this weekend to write out > exactly what kind of changes there would need to be in the static and > runtime semantics in the current spec. The overall goal is to keep the > import syntax simple and expand the static and runtime semantics to support > that simplicity. This includes continuing to support the ability to handle > cyclic dependencies. Engine authors will need to write the code for the > import semantics once, while the development community will use the import > syntax over and over for some time to come. It seems like a simpler syntax > should win out over possibly changing the semantics. > > > > Best regards, > > Ron > > > > > > > > > > p.s. Here are some examples of various inputs and outputs based on this > proposal: > > > > # Exports > > > > [named-exports.js] > > ``` > > export var version = "1.0"; > > export function println(text) { console.log(text); } > > ``` > > > > [single-export.js] > > ``` > > function hello (text) { alert("Hello " + text + "!"); } > > hello.goodbye = function (text) { alert("Goodbye " + text + "!"); } > > export default hello; > > ``` > > > > [multi-export-with-default.js] > > ``` > > // if (A) above, this is an early error > > // if (B) above, version becomes Person.version > > export default class Person { > > jump() { return "How high?"; } > } > > export var version = "2.0"; > > ``` > > > > [single-export-of-object.js] > > ``` > > export default { > > version: "1.0", > > assert(test) { if (!test) throw new Error("failed!"); } > > } > > ``` > > > > # Imports > > > > [import-named-imports.js] > > ``` > > import namedExports from "named-exports"; // namedExports = binding to > Import.[[Value]] which results in a Module object with properties "version" > and "println"; > > import { version, println } from "named-exports"; // version = binding to > Import.[[Value]].version, println = binding to Import.[[Value]].println > > // or... > > import namedExports, { version, println } from "named-exports"; // both of > the above > > ``` > > > > [import-single-export.js] > > ``` > > import hello from "single-export"; // hello = binding to Import.[[Value]] > which results in the "hello" function > > import { goodbye } from "single-export"; // goodbye = binding to > Import.[[Value]].goodbye > > // or... > > import hello, { goodbye } from "single-export"; // both of the above > > ``` > > > > [import-multi-export-with-default.js] > > ``` > > // assumes (B) above > > import Person from "multi-export-with-default"; // Person = binding to > Import.[[Value]] which results in the "Person" class > > import { version } from "multi-export-with-default"; // version = binding > to Import.[[Value]].version > > // or... > > import Person, { version } from "multi-export-with-default"; // both of > the above > > ``` > > > > [import-single-export-of-object.js] > > ``` > > import test from "single-export-of-object"; // test = binding to > Import.[[Value]] which results in an Object with properties "version" and > "assert" > > import { version, assert } from "single-export-of-object"; // version = > binding to Import.[[Value]].version, assert = binding to > Import.[[Value]].assert > > // or... > > import test, { version, assert } from "single-export-of-object"; // both > of the above. > > ``` > > > > > > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss