【javascript】モジュール

こちらの記事は以下の書籍を参考に執筆しました

- [入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


#モジュールとは

- 最も基本的なものは独自のスコープとルールを持つ1つのjavascriptファイル
- モジュールはオブジェクトではない
- モジュールにデータ型はない
- モジュールを変数に代入できない
- コードの分割、カプセル化、構成をするためのツール

モジュールを利用すれば必要なものをインポートし、認知不可を抑え、メンテを楽にしてくれる。

#モジュールのルール
javascriptのルールはモジュールのないでは少し違ってくる。

- 常にScriptモードで実行されるため、use scriptを追加する必要はない。
- thisがルートコンテキストで何を示すか

#####thisがルートコンテキストで何を示すか
ES2015のモジュールではルートレベルのthisはundefinedになる。

```javascript
var obj = {
  foo() {
    return this;
  }
}

function bar() {
  return this;
}

obj.foo(); //obj
bar(); //undefined
console.log(this) //undefined
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



モジュールは変数がグローバル変数として定義されることはない。
しかしモジュール内部でグローバルオブジェクトに値を割り当てることは可能。

とはいえモジュールのグローバルの設定は悪い作法。

#モジュールを作成
##デフォルトエクスポート
グローバル関数はこう書くかもしれない

```javascript
window.logState = functionn(stat) {
  //処理
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


しかしモジュールではこう書く

```javascript
export default function logState(start){
  //処理
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


関数の先頭にexportをつけるとこのモジュールがlogState関数をいエクスポートするようになる。このエクスポートのことをデフォルトエクスポートという。

##エクスポートしたくない関数があるとき
モジュールを使用せず、ヘルパー関数をエクスポートしたくないとしたらこう書くかもしれない。

```javascript
{
  function statsHellper() {
    //処理
  }

  window.logState = functionn(stat) {
    //処理
  }

}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


しかしモジュールを使うならすべてのものが独自のスコープに含まれているため、値が漏れることはない。

```javascript
function statsHelper() {
  //処理
}

export default function logState(start) {
  //処理
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



##名前付きエクスポート
モジュールを関数として考えるとexport defaultはreturnに相当する。
関数から返せる値は1つであるようにモジュールのデフォルトエクスポートは1つだけ。

しかしデフォルトエクスポートが1つだけなのであって、モジュールのエクスポートが1つに制限されるわけではない。
デフォルト以外は**名前付きエクスポート**になる。
名前付きは単にdefaltが消えただけ。

```javascript
export function logState(start) {
  //処理
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



名前は関数名になる。
###名前付きエクスポートのもう一つの構文
名前付きエクスポートにはもう一つ構文がある。

```javascript
function logState(num){
  //処理
}
export{logState}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


構文はこう

```javascript
export{<バインディング1>,<バインディング2>,...}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


好きなだけ指定することもできる。
##名前を変えてエクスポート
名前を変えてエクスポートもできる
内部でformattedCurrentusernameをusernameでエクスポートするにはこうする。

```javascript
export { formattedCurrentUsername as username}
```
##変数宣言でも関数同様
変数宣言でも件数と同じことが当てはまる。

```javascript
export let one = 1//oneという名前でエクスポート
export const two = 2//twoという名前でエクスポート
export 3//無効：名前を推測できない
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)



##exportはトップレベルに配置する
条件付きで値をエクスポートはできない。
トップレベルとはファイル内のコードブロックの本体、if文、関数ではなく、コードブロックのルートを意味する。

```java
//トップレベルなので有効
export const number = num => //処理
  //トップレベルでない
if () {
    export const number = num => //処理
}

//トップレベルでない
function
export () {
  export const number = num => //処理
}
```
>出典：[入門JavaScriptプログラミング](https://www.amazon.co.jp/%E5%85%A5%E9%96%80JavaScript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-JD-Isaacks/dp/479815864X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1F76CKY9CIJ66&dchild=1&keywords=%E5%85%A5%E9%96%80javascript%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1595991879&s=books&sprefix=%E5%85%A5%E9%96%80javascript%2Cstripbooks%2C-1&sr=1-3)


#javascriptファイルはどのタイミングでモジュールになるか
基本的に\<script\>のtype='module'とするとそのファイルをモジュールとして実行するようになる。
##別の方法

Node.jsには\<script\>タグを使用しないため上の方法では使えない。
別の方法としてこのようなものがある。

```javascript
export {}
/* モジュールの残りの部分 */
```

これはオブジェクトのエクスポートではない。
これは本来なら{}の間にエクスポートする名前を指定する名前付きエクスポート構文。
何もエクスポートされないが、これがあることでこのファイルはモジュールと認識される。


#まとめ

- 宣言をエクスポートするときは、名前付きエクスポートが作成される。
- 名前付きエクスポートは別名も指定できる。
- 名前付きはいくつでもいいが、デフォルトエクスポートは1つだけ
- exportはトップレベルで記述
- ルートレベルではthisはundefinedになる
- モジュールはデフォルトでScriptモードになる