【初心者】エクスポート・インポート記述メモ（ ECMAScript Modules [ ESM ] 構文 ）【備忘録】


# はじめに
投稿時点で、筆者は知識ゼロの状態から勉強を初めて2ヶ月程度の実力です。
そのため、理解不足や説明不足、誤った内容や呼び方をしている可能性があります。
万が一参考にする場合は上記の点を考慮した上でご一読ください。
説明文の内容はChatGPT先生からの引用も多いです。

# 本題
「ECMAScript Modules」
以下、ChatGPT先生より引用。
>ECMAScript ModulesとCommonJS Modulesは、JavaScriptのモジュールシステムの2つの主要な形式です。これらの形式は、異なるシステムで使用されるため、それぞれの違いを理解することが重要です。
ECMAScript Modulesは、JavaScriptの標準化団体であるECMA Internationalによって標準化された形式で、ブラウザやNode.jsなどの環境で使用されます。この形式は、importおよびexportステートメントを使用して、モジュール間でコードを共有する方法を提供します。また、静的な構造を持ち、モジュールの読み込みは非同期的に行われます。
簡単に言うと、ECMAScript Modulesは、importおよびexportステートメントを使用して、静的な構造を持ち、非同期的にモジュールを読み込むことができます。

CommonJS Modulesのエクスポート・インポート記述については下記にまとめました。
[【初心者】エクスポート・インポート記述メモ（ CommonJS Modules構文 ）【備忘録】](https://qiita.com/miyaayim_study/items/dd5beb29f0ee4e245dc0)

ここでは関数、定数のエクスポート・インポートを例にしています。
## 名前なしエクスポート / 名前なしインポート（Named Exports / Default Imports）

### 特徴
- 渡せるファイルは1ファイル1つの値のみ
- インポート時に名前を自由に変更可能

### 使い方

- エクスポート
直接エクスポート（出力）する場合は、先頭に`export default`を書く。
定義してからエクスポートする場合は、`export default 名前`とする。

- インポート
インポート（読込）する場合は、`import 名前 from './ファイル名'`と書く。
インポート時は、エクスポート時の名前と異なる名前をつけてもOK（もちろん同じでもOK）。

わかりづらいが、`default`という名前でエクスポートされてるイメージ。

### エクスポート例
下記は全て同じ動作です。
#### ～ 通常の関数の場合 ～

##### 1.名前なし関数（関数式 [ 無名関数 / 関数リテラル ]）

```jsx
export default function () { /*…*/ }; // 無名関数を直接デフォルトでエクスポート
```

```jsx
const Counter = function () { /*…*/ }; // 無名関数をCounterという定数名で定義
export default Counter; // 定数Counterをデフォルトでエクスポート
```

##### 2.名前付き関数（関数宣言 [ function文 ] ）

```jsx
export default function Counter() { /*…*/ }; // Counterという関数を定義し、それを直接デフォルトでエクスポート
```

```jsx
function Counter() { /*…*/ }; // 関数をCounterという関数名で定義
export default Counter; // 関数Counterをデフォルトでエクスポート
```

```jsx
function myFunction() { /*…*/ }; // 関数をmyFunctionという関数名で定義
const Counter = myFunction; // 関数myFunctionをCounterという定数名で定義
export default Counter; // 定数Counterをデフォルトでエクスポート
```

#### ～ アロー関数の場合 ～

アロー関数では、通常の関数定義とは異なり、名前付き関数を定義することはできません。
アロー関数では **`function`** 文を使用せずに名前付き関数を定義することはできません。

##### 名前なし関数（関数式 [ 無名関数 / 関数リテラル ]）

```jsx
export default () => { /*…*/ }; // 無名のアロー関数を直接デフォルトでエクスポート
```

```jsx
const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義
export default Counter; // 定数Counterをデフォルトでエクスポート
```

#### ～ NG例 ～

2つの値を渡しているのでNG、デフォルトエクスポートは1ファイル1つの値のみ。

```jsx
const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義
const Button = () => { /*…*/ }; // 無名のアロー関数をButtonという定数名で定義
export default Counter; // 定数Counterをデフォルトでエクスポート
export default Button; // 定数Buttonをデフォルトでエクスポート
```

### インポート例

```jsx
import App from './modules'; // './modules'からデフォルトでエクスポートされた値を、Appという名前でインポート（自由に名前を指定できる）
```


### 使用例

```jsx:components/modules.js
const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義
export default Counter; // 定数Counterをデフォルトでエクスポート
```

```jsx:components/index.js
import App from './modules'; // './modules'からデフォルトでエクスポートされた値を、Appという名前でインポート（自由に名前を指定できる）
```

## 名前付きエクスポート / 名前付きインポート（Named Exports / Named Imports）

### 特徴

- 複数のファイルを渡せる
- インポート時に名前の変更不可

### 使い方

- エクスポート
直接エクスポート（出力）する場合は、先頭に`export`を書く。
定義してからエクスポートする場合は、`export { 名前 }`とする。
直接エクスポートする場合は、名前を`{}`で囲む必要はない。
複数エクスポートする場合は、`export { 名前, 名前 }`のようにカンマで区切る。

- インポート
インポート（読込）する場合は、`import { 名前 } from './ファイル名'`と書く。
複数インポートする場合は、`import { 名前, 名前 } from './ファイル名'`のようにカンマで区切る。
名前なしインポートと違い、インポート時はエクスポート時と同じ名前を書く。






### エクスポート

下記はどれも同じ動作です。

#### ～ 通常の関数の場合 ～

名前無し関数はその名前がないため、直接名前付きエクスポートすることはできません。

##### 1.名前なし関数（関数式 [ 無名関数 / 関数リテラル ]）

```jsx
const Counter = function () { /*…*/ }; // 無名関数をCounterという定数名で定義
export { Counter }; // 定数Counterをエクスポート
```

##### 2.名前付き関数（関数宣言 [ function文 ] ）

```jsx
export function Counter() { /*…*/ }; // Counterという関数を定義し、それを直接エクスポート
```

```jsx
function Counter() { /*…*/ }; // 関数をCounterという関数名で定義
export { Counter }; // 関数Counterをエクスポート
```

```jsx
function myFunction() { /*…*/ }; // 関数をmyFunctionという関数名で定義
const Counter = myFunction; // 関数myFunctionをCounterという定数名で定義
export { Counter }; // 定数Counterをエクスポート
```

#### ～ アロー関数の場合 ～

##### 名前なし関数（関数式 [ 無名関数 / 関数リテラル ]）

```jsx
export const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義し、それを直接エクスポート
```

```jsx
const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義
export { Counter }; // 定数Counterをエクスポート
```

### インポート例
通常のインポートの場合
```jsx
import { Counter } from './modules'; // './modules'からCounterという名前でエクスポートされた値をインポート（名前はエクスポート名と同じであること）
```
名前付きエクスポートされたのを、別のファイル先で使用するために再エクスポートする場合。
メリットとしては、インポート→エクスポートの手順を省略できること。
ただし、再エクスポートであってインポートではないので、今のファイル内で使用するならインポートが必要。

```jsx
export { Counter } from './modules'; // './modules'からCounterという名前でエクスポートされた値をそのままエクスポート（名前はエクスポート名と同じであること）
```

### 使用例

#### ～ 複数の値をエクスポート ～

```jsx:components/modules.js
export const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義し、それを直接エクスポート
export const Button = () => { /*…*/ }; // 無名のアロー関数をButtonという定数名で定義し、それを直接エクスポート

//または

const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義
const Button = () => { /*…*/ }; // 無名のアロー関数をButtonという定数名で定義
export { Counter, Button }; // 定数Counterと定数Buttonの2つをエクスポート
```

#### ～ 複数の値をインポート ～

```jsx:components/index.js
import { Counter } from './modules'; // './modules'からCounterという名前でエクスポートされた値をインポート（名前はエクスポート名と同じであること）
import { Button } from './modules'; // './modules'からButtonという名前でエクスポートされた値をインポート（名前はエクスポート名と同じであること）

// または

import { Counter, Button } from './modules'; // './modules'からCounterとButon、それぞれの名前でエクスポートされた値をインポート（名前はエクスポート名と同じであること）
```

#### ～ エクスポートの同時使用 ～

名前付きエクスポートと名前なしエクスポートは同時に使用可能

```jsx
export const Counter = () => { /*…*/ }; // 無名のアロー関数をCounterという定数名で定義し、それを直接エクスポート
export default Counter; // 定数Counterをデフォルトでエクスポート
```

このコードは、 `Counter` 関数を名前付きエクスポートとしてエクスポートし、同じ `Counter` 関数をファイルのデフォルトエクスポートとしてエクスポートしています。したがって、他のモジュールからこのファイルをインポートする場合、名前付きエクスポートとして `Counter` 関数をインポートするか、デフォルトエクスポートとして `Counter` 関数をインポートするか、自由に選択できます。

## 別名エクスポート、別名インポート（Alias Export / Alias Import）

名前付きエクスポート・名前付きインポートの中には別名エクスポート・別名インポートという`as`を使った手段もある。
`as`は直訳すると「として」という意味。

### 特徴

- エクスポート・インポートした値を、名前を変更して再エクスポート・インポートすることができる。
- 別名エクスポートで再エクスポートする時は、インポートする作業を省略することができる。（エントリポイントを使用する場合に便利）

### 使い方

- エクスポート
定義してからすエクスポート（出力）する場合に使用できる。
別名エクスポートする場合は、`export { 名前 as 変更後の名前 }`とする。
複数別名エクスポートする場合は、通常の名前付きエクスポートのようにカンマで区切る。

- インポート
インポート（読込）する場合は、`import { 名前 as 変更後の名前 } from './ファイル名'`と書く。
複数別名インポートする場合は、通常の名前付きインポートのようにカンマで区切る。

### 使用例

#### 1.別名エクスポート

```jsx
const myConst = () => { /*…*/ }; // 無名のアロー関数をmyConstという定数名で定義
export { myConst as Counter }; // 定数myConstをCounterという名前でエクスポート
```



#### 2.名前なしエクスポートされたのを別名インポート

```jsx
import { default as Counter } from './modules'; // './modules'からデフォルトでエクスポートされた値を、Counterという名前でインポート
```

#### 3.名前付きエクスポートされたのを別名インポート

```jsx
import { myConst as Counter } from './modules'; // './modules'からmyConstという名前でエクスポートされた値を、Counterという名前でインポート
```

#### 4.エントリポイントを経由して再エクスポート

エントリポイント（index.js）で再エクスポートする際は、わざわざインポートする必要はない。
下記では、`myConst` → `default` → `Counter` という順番で名前が変化しているイメージ。

```jsx:components/modules.js
const myConst = () => { /*…*/ }; // 無名のアロー関数をmyConstという定数名で定義
export default myConst; // 定数myConstをデフォルトでエクスポート
```

```jsx:components/index.js
export { default as Counter } from './modules'; // './modules'からデフォルトでエクスポートされた値を、Counterという名前で再エクスポート
```

```jsx:main.js
import { Counter } from './components/index.js'; // './components/index.js'からCounterという名前でエクスポートされた値をインポート
```





# 参考リンク
MDN
[export - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export)
[import - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)

特に役立ったサイト
[JavaScriptのexport/importについて調べた](https://shkn.hatenablog.com/entry/2019/05/19/173313)
[JavaScriptでのimport/export方法](https://qiita.com/koeri3/items/314ac7b9b73fc8c80a2d)
[#05 新・日本一わかりやすいReact入門【基礎編】コンポーネントのimportとexport](https://www.youtube.com/watch?v=Sex6Vc-NJEk)

役立ったサイト
[JavaScript export default されたものを as で import したい](https://chaika.hatenablog.com/entry/2020/05/14/083000)
[「export default, import」の注意点](https://zenn.dev/mo_ri_regen/articles/7a261a66e3bbed)
[export, export defaultの違い](https://qiita.com/keitean/items/9e6580c639054ab14d42)
[export defaultとexportの違いは何か？指定した複数の変数や関数、処理を別の.jsや.vueファイルにインポートする方法｜モジュール名を指定・変更する方法(defaultありなし)](https://prograshi.com/language/javascript/export-default-and-export/)
[JavaScriptでのimport/export方法](https://qiita.com/koeri3/items/314ac7b9b73fc8c80a2d)
[JavaScriptのimport exportについて](https://zenn.dev/fqqk/articles/88461528013104)
[JSの import/export をすぐ忘れるのでいい加減まとめてみた](https://zenn.dev/tatsurom/articles/842f53cc7df996b861c7)
[【初心者必見】JavaScriptのimportとexportのやり方](https://god48.com/javascript-import-export)
[JavaScript export default されたものを as で import したい](https://chaika.hatenablog.com/entry/2020/05/14/083000)
[【JavaScript】１分で理解する！=>アロー関数の基本](https://it-biz.online/web-design/arrow-function/)