What is the difference between importing a function expression or declaring a function from an ES6 module?

As I understand it ( see section 16.3.2.1 ), ES6 allows various syntaxes for function / class export operands. The difference is whether the exported function should be interpreted upon import as a function declaration, in which case you write: export default function () {} // (a) or as a function expression: export default (function () {}); // (b) export default (function () {}); // (b) .

As a possible related sidenite: I read that imports are rising, but I'm not quite sure what this means in this context.

Taking an example of this example:

import foo from 'my_module'; // (c)

As I understand it, the above statement will save my exported function in the variable foo . Is this variable raised, or what is, and when?

Most importantly, what's the difference (in terms of setting foo ) when my_module exports a function using (a) and when it exports it using (b) ?

+8
javascript ecmascript-6 es6-modules
source share
1 answer

Your question is a bit confusing, but I will try to explain everything.

First, let's determine how the modules as a whole work. The module has a set of exported names, each of which refers to a local variable in this module. The export name should not be the same as the local binding name. One of the exported names may be default , for which there is a special syntax (both in export and import), designed for the case when the module exports only one thing.

I read that they are imported, but I'm not sure what this means in this context:

 import { foo } from 'my_module'; 

Yes, import ads are rising. Like var or function (and in fact like any other declaration ), the identifier foo is available from the very beginning, before any statements in the module are executed. In fact, a binding is even created before those declared by var iables.

The difference is how they are initialized:

  • var initialized with undefined
  • function and function* initialized by a function object
  • let , const and class es remain uninitialized
  • the imported bindings are not even initialized, they are created as a pointer to a local variable referenced by the exported name in the imported module
  • imported modules ( import * as … ) are initialized by a module object (whose properties are also such pointers)

When is foo set to reference my exported function?

Short answer: in front of everything else.

Long answer: it really is not installed. This is a link to a local variable in the imported module that you expect to save. A local variable can change if it is not const , but we usually do not expect this. And usually it already contains this function, because the imported module is fully evaluated before the module (s) that imports it. So if you are afraid that the problem is with var functionName = function () {} vs function functionName () {} , you can free yourself - no.

Now back to your question title:

What is the difference between exporting a function expression and a function declaration in an ES6 module?

Nothing special, the two aspects do not really have much to do with each other:

  • export declarations associate the export name with a local variable in the scope of the module
  • All variables in the module area are raised as usual.
  • function declarations are initialized differently than variable declarations with the function expression assigned as usual

Of course, there is still no good reason not to use declarative declarations everywhere; this is no different in ES6 modules than before. If at all, there may be even less reason to use function expressions, since everything is covered by declarations:

 /* for named exports */ export function foo() {…} // or function foo() {…} export {foo as foo} 

 /* for default exports */ export default function foo() {…} // or function foo() {…} export {foo as default} // or function foo() {…} export default foo; // or export default function() {…} 

Well, the last two default export declarations are actually slightly different from the first two. The local identifier associated with the exported default name is not foo , but *default* cannot be reassigned. This makes sense in the latter case (where there is no name foo ), but in the second and last case you should notice that foo is really just a local alias, not the exported variable itself. I would recommend not using this template.

Oh, and before you ask: Yes, the last default export is really a function declaration, not an expression. Anonymous function declaration. This is new with ES6 :-)

What is the difference between export default function () {} and export default (function () {});

They are almost the same for all purposes. These are anonymous functions with the .name property "default" , which are stored in this special binding *default* , to which the exported default name indicates for anonymous export values.
Their only difference is the rise - the declaration will receive its function created at the top of the module, the expression will be evaluated only after the execution of the module code reaches the instruction. However, given that there is no variable with an accessible name for them, this behavior is not observed, except in a special special case: a module that imports itself. Hm, yes.

 import def from "myself"; def(); // works and logs the message export default function() { console.log("I did it!"); } 

 import def from "myself"; def(); // throws a TypeError about `def` not being a function export default (function() { console.log("I tried!"); }); 

You really shouldn't do any of these things anyway. If you want to use the exported function in your module, specify it in the declaration.

In this case, why are there both syntaxes?

It happens. This is allowed by the specification, because it does not make unnecessary exceptions to prohibit some meaningless things. It is not intended to be used. In this case, the specification even explicitly prohibits function and class expressions in export default expressions and treats them as declarations. Using the grouping operator, you have discovered a loophole. Well done. Do not abuse it.

+14
source share

All Articles