15

What is the difference if any between exporting an es6 default class inline with its definition versus at the end of the file after its definition?

Following are two examples I came across in React tutorials.

Ex. 1: Inline with Class

export default class App extends React.Component {
    // class definition omitted
}

Ex. 2: End of file

class App extends React.Component [
    // class definition omitted
}

export default App; // is this different somehow?

If there is no difference, then it seems the first example is more efficient and concise.

ThisClark
  • 14,352
  • 10
  • 69
  • 100
  • yep, it's just a personal preference thing. Some people like all their exports in one place, some are used to exports & definitions happening on their own lines, etc, etc – Hashbrown Feb 07 '20 at 01:53
  • Looks like a style question. If you only have that class, and only one export, the first indeed looks more concise. However, if you have more code in the file, and a reader would need to search for "export" first, maybe putting all exports at the end of the file is easier to read. – ASDFGerte Feb 07 '20 at 01:53

1 Answers1

8

The only significant difference is that, when exporting something other than a class or a named function declaration, declaring the expression and then exporting it afterwards allows you to reference it elsewhere in the same module.

Class names and (non-arrow, named) function declarations have their name put into the module's scope as a variable:

<script type="module">
export default class App {
    // class definition omitted
}
console.log(typeof App);
</script>

<script type="module">
export default function fn() {
    
}
console.log(typeof fn);
</script>

But this isn't possible for other sorts of expressions, like plain objects or arrow function expressions, which don't intrinsically have a name associated with them:

<script type="module">
export default {
  prop: 'val'
  // There's no way to reference the exported object in here
}
// or out here
</script>

<script type="module">
export default () => 'foo';
// There's no way to reference the exported function elsewhere in this module
</script>

Well, there's one way to get back a reference to it, which is by importing the current module that you're in:

// foo.js
import foo from './foo';
export default () => {
  console.log('foo is', typeof foo);
};

But that looks really ugly and confusing.

So if you're default-exporting something which isn't a class nor a function declaration, you can't easily reference what you're exporting unless you put it into a standalone variable before exporting it.

Keep in mind that this is not the case for named exports, which can easily be referenced by the name of their export:

<script type="module">
export const obj = {
  prop: 'val'
};
console.log(typeof obj);

export const fn = () => 'foo';
console.log(typeof fn);
</script>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • "*there's no way to reference what you're exporting*" - or unless you import it from yourself ([\[1\]](https://stackoverflow.com/a/43663635/1048572), [\[2\]](https://stackoverflow.com/a/35225936/1048572)) :-) – Bergi Feb 07 '20 at 02:05