JavaScript: Default Exportは、値を「default」という名前でNamed Exportしている

JavaScriptのdefault exportは、「default」という名前でnamed exportをしているということになります。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">いや　ES Modulesにおいてdefault exportは「defaultという名前でnamed exportする」こととして定義されている（ぇ</p>&mdash; 🈚️うひょ🤪✒📘 (@uhyo_) <a href="https://twitter.com/uhyo_/status/1250587929438633984?ref_src=twsrc%5Etfw">April 16, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

この投稿では、具体的なコードを示しながら、default exportにちゃんと「default」という名前がついているのを確認していきたいと思います。

## named export と default export

まず、おさらいとして、named exportとdefault exportの書き方を見比べてみます。

```module.js
// named export
export const foo = 1

// default export
export default 1
```

named exportのほうは、変数名がついていますが、default exportのほうは、値です。

これらをインポートするコードは次の例のようになります。named exportの値は`module.js`で決められた名前でインポートします。それに対し、default exportの値は使う側の`main.js`が変数名を決めます。下の例では`bar`と名づけています。

```main.js
// named export
import { foo } from "./module.js"

// default export
import bar from "./module.js"
```

## よくある誤解

上のコードだけで2種類のexportを比べてみると、その違いは次のようなものだと思うのではないでしょうか？

* named export: 名前がついているエクスポート
* default export: 名前がついていないエクスポート

これはよくある誤解のようです。誤解とまではいかずとも、もう少し的確なメンタルモデルがあります。

[MDN web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export)では、2つの違いを次のように説明しています:

> エクスポート方法は、名前付きとデフォルトの 2 種類あります。名前付きエクスポートはモジュールごとに複数持てますが、デフォルトエクスポートは 1 つに限ります。

「exportを何個持てるか」についてだけ言っていて、「名前がついているか」については言っていないのです。

## defaultという「名前」がつく

なぜ、名前の有無が語られないかというと、default exportでエクスポートされた値には「default」という名前が与えられるためと考えられます。

例えば、次のdefault exportは、

```js
export default 1
```

いわば、次のようなnamed exportと同じような意味合いなのです。

```js
export const default = 1
```

ただ、`default`が予約語なので、`default`という変数を定義することはできません。なので、当然`const default`なんてものををnamed exportもすることはできません。

## defaultという名前がつくのを確認する方法

「それは内部的な話なんでしょう？ defaultという変数にプログラマが触れられないなら、別に気にすることでもないんじゃ？」

そう思われそうですが、JavaScriptのコード上でもいくつか「default」という変数を参照できる例があります。場合によっては`default`という変数を参照する必要が出てくるコードもあります。

例えば、`import * as name`構文を使ったコードです:

```js
// helloWorld.js
export default function () {
  console.log('Hello World')
}

// main.js
import * as module from './helloWorld.js'
module.default()
//出力結果: Hello World
```

`helloWorld.js`で`export default`された関数が、`main.js`では`default`という変数に入っていることが確認できます。

2つの目の例は、dynamic importです:

```js
// helloWorld.js
export default function () {
  console.log('Hello World')
}

// main.js
import('./helloWorld.js')
  .then(module => module.default())
  //出力結果: Hello World
```

これも同様に`main.js`では、関数が`default`という名前の変数に入ってきます。dynamic importでは、この`default`という変数にアクセスしないと、default exportされたものを利用することができません。

3つめの例は、`export { variable as name }`構文(エクスポート時の名前変更構文)を使った場合も、`default`という名前の出現が確認できます:

```js
// helloWorld.js
const func = function () {
  console.log('Hello World')
}

export { 
  func as default, // ここ
  func as helloWorld
}

// main.js
import func from './helloWorld.js'
import { helloWorld } from './helloWorld.js'
func() //=> Hello World
helloWorld() //=> Hello World
```

以上が、プログラマが実際にJavaScriptのコード上で「default」という名前を確認できる例でした。

## まとめ

default exportされた値には、「default」という名前が与えられる。

## 所感

一見特別そうなdefault exportですが、勝手に「default」という名前を付けてくれるnamed exportだと思うと、なんとなく整理されたような気がしてきます。

---

最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします:relieved:→[Twitter@suin](https://twitter.com/suin)