export / import する時の{ }中括弧について【javascript】

## はじめに

どっちの時に {  } をつける？つけない？ 
**default export / import**
**named export / import**　

## defalut export / import には気をつけろ！
:::note info
default exportは、モジュール内で **1つだけ** エクスポートすることができる。
:::
:::note info
import時に **独自の名前** を作成する必要がある。
:::

:::note warn
異なる名前を使用することができてしまうという罠
・誤用される余地がある。
・exportする関数名や変数名が変わって、名前の不一致につながりやすい。
　（呼び出し側ではエラーが出ない）
:::
:arrow_down: import時、関数名や変数名を変えると、コードの保守性や可読性を損なう。
```javascript:exportするファイル
const hogeFn = () => {
  return <h1>サンプル</h1>;
}

export default hogeFn;
```

```javascript:importするファイル
import hogeFn from './Hoge' //　　通常、名前を変える事なく直接使用できる。

import fugaFn from './Hoge' // hogeFnをfugaFn（export時の別名）としてもエラーにならない。
```
:arrow_down: import時、変数名が変わっても参照する値は同じ（直感的にわからない）
```javascript:exportするファイル
const a = 100;
export default a; // モジュール内から1つだけexportできる
```
```javascript:importするファイル
import b from "./Hoge"; // 'a'→'b'（export時の別名）としても、'b'は'a'の値を参照
console.log(b); // 100
```
## named export / import に対して { } が使える
:::note info
named export / importはモジュールごとに複数持てる。
:::
:::note info
export時とimport時の名前が一致している必要がある。
:::


```javascript:exportするファイル
const testVar = 'test'
const testFunc = () => console.log('Function')
// 作成した変数や関数を{ }を使用し複数exportできる。 
export { testVar, testFunc }

// 変数や関数の宣言と同時にエクスポートすることも可能
// export const testVar  = 'test';
// export const testFunc = () => console.log('Function');
// var, let, const, function, class がエクスポート可能
```

```javascript:importするファイル
// 同じファイルで両方でも、片方だけでも使用する事が可能。export時点と変数名、関数名は同じ。
import { testVar, testFunc } from './Test'
// named export/importの場合は、単体でも{ }を使う。
import { testVar } from './Test'

console.log(testVar); //　'test'
testFunc(); // 'Function'とコンソール出力される

////////////////// as 別名 でimportする事もできる。 //////////////////
import { testVar as myVar, testFunc as myFunc } from "./Test"

console.log(myVar); //　'test'
myFunc(); // 'Function'とコンソール出力される
```
## 結果
|  | default export | named export |
|:-----------|:------------:|:------------:|
| exportできる数 | 1つ | 複数でも可 |
| import時の名前 | 任意 | export時と同じ |
| {  } | :heavy_multiplication_x:　| :o: |

## おまけ 1 :集約する時、ワイルドカード　*　の使い方に注意

:::note alert
import * from "mod"; → 使えない
:::

:::note info
import * **as 任意の別名** from "mod"; 
:::

**import集約**：複数の名前付きエクスポートを1つのオブジェクトとしてまとめて利用するために使用される。これにより、同じ名前の変数や関数が他のインポートと衝突するリスクを減らすことができる。また、異なるモジュールから同じ名前のエクスポートが行われている場合、別名を付けてそれぞれを区別する必要がある。

```javascript:
// exportするTest.jsファイル
export const a = 100;
export const b = 200;
```
```javascript:
// importするファイル
import * as testModule from "./Test";

console.log(testModule.a); // 100
console.log(testModule.b); // 200
```
import * as testModule from "./Test"; は、Test.js でエクスポートされたすべての名前付きエクスポート（a と b）を testModule という名前のオブジェクトに集約。これにより、testModule.a および testModule.b を使ってそれぞれの値にアクセスすることができる。

:::note info
export * from "mod"; 
:::
mod モジュールのすべての名前付きエクスポートを現在のモジュールから再エクスポートするための文。使い所として注意するべきは、同じ名前でエクスポートしない事。
```javascript:
// -- mod1.js --
export const a = 1; //　　名前付きエクスポート

// -- mod2.js --
export const a = 3; // 名前付きエクスポート

// -- barrel.js --　
export * from "./mod1.js";
export * from "./mod2.js";

// -- main.js --
import * as ns from "./barrel.js"; //集約import
console.log(ns.a); // undefined　
//共通の名前aで再エクスポートする2つのワイルドカードのexport文があったため衝突し、undefined
```

## おまけ2：セミコロンはつける？つけない？

:::note info
**関数宣言には、末尾のセミコロンは不要。**
export function functionName() { /* … */ }
export class ClassName { /* … */ }
クラスや関数の前の export はそれを 関数式 にはしない。
エクスポートされているが、関数宣言です。


:::
:::note info
**リストのエクスポートには、末尾にセミコロンはつける。**
export { name1, /* …, */ nameN };

:::
```javascript:
function sayHello(user) {
  console.log(`Hello, ${user}!`);
}

function sayBye(user) {
  console.log(`Bye, ${user}!`);
}

export {sayHello, sayBye}; // エクスポートされた変数のリストには末尾にセミコロンをつける

```
## おまけ3：実際のエラーメッセージ
> **export 'Item' (imported as 'Item') was not found in './Item' (possible exports: default)**

:point_up:default exportに対して、import { } from XX の形式でimportしたために、不一致となりエラーが発生
```javascript:exportするファイル
// Item.js
const Item = { name: 'Hoge' };
export default Item;
```
```javascript:importするファイル
import Item from './Item'; 
//　import { Item } from './Item';　にするとエラーが発生するので注意！！
```

## 参考
[export - JavaScript | MDN](
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export)
[import - JavaScript | MDN](
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import)
[エクスポートとインポート](https://ja.javascript.info/import-export)
[named exportとdefault exportの違いを理解する](https://zenn.dev/yuji6523/articles/373a675275abc4)
[JavaScript: Default Exportは、値を「default」という名前でNamed Exportしている](
https://qiita.com/suin/items/b585ad68beec78099ee5)