[[JavaScript]]章では最後のLessonになります。[[JavaScript]]、そして[[TypeScript]]を実利用するうえで大きな障壁となりうる[[モジュール (JavaScript)|モジュール]]について理解しましょう。
## Reference
- [ECMAScriptモジュール · JavaScript Primer \#jsprimer](https://jsprimer.net/basic/module/)
## Lesson
[[モジュール (JavaScript)|モジュール]]とは、プログラムを機能ごとに分割し、再利用性を高めるためにそれらをexport/importできるようにする仕組みのことです。
[[JavaScript]]で扱うことのできる[[モジュール (JavaScript)|モジュール]]にはいくつか種類があります。ここでは、モダンかつ[[Deno]]でも利用できる[[ESモジュール (JavaScript)|ESモジュール]]についてのみピックアップします。
> [!attention]
> これから説明する内容は、各単元において完全な説明ではありません。重要な点のみを理解しやすくするため、**敢えて説明を省いて**います。正式な定義や説明は一次情報をご覧ください。
### ESモジュール
正式名称は[[ESモジュール (JavaScript)|ECMAScript modules]]ですが、呼びやすさから[[ESモジュール (JavaScript)|ESモジュール]]や[[ESモジュール (JavaScript)|ESM]]と呼ばれることが多いです。
`import` でインポート、`export` でエクスポートを行います。[[import (ESM)|import]]と[[export (ESM)|export]]にはいくつか種類がありますが、特に知っておいた方がいいのは以下3つです。
- [[名前付きexport (ESM)|名前付きexport]]
- [[名前付きimport (ESM)|名前付きimport]]
- [[名前空間import (ESM)|名前空間import]]
### 名前付きexport
頭に `export` キーワードを追加することで、[[名前付きimport (ESM)|名前付きimport]]や[[名前空間import (ESM)|名前空間import]]でそれらをインポートできるようになります。
```js
// libs.js
export const name = "tatsuwo";
export function hello() {
console.log("hello");
}
```
### 名前付きimport
[[名前付きexport (ESM)|名前付きexport]]でエクスポートした変数や関数などをインポートして使用できます。
```js
import { hello, name } from "./libs.js";
console.log(name);
hello();
```
### 名前空間import
[[名前付きexport (ESM)|名前付きexport]]で指定した変数や関数などを**1つの[[namespace (JavaScript)|名前空間]]として**インポートできます。
```js
import * as libs from "./libs.js";
console.log(libs.name);
libs.hello();
```
### その他
使用するライブラリによっては、[[デフォルトexport (ESM)|デフォルトexport]]を使っています。[[デフォルトimport (ESM)|デフォルトimport]]とセットで認知はしておきましょう。
## Mission 1
#😁EASY
以下のファイルから `sum3` の定義を別ファイル `./libs.js` に切り出すようにリファクタリングしてください。
```js
function sum3(x, y, z) {
return x + y + z;
}
const r = sum3(1, 10, 100);
console.log(r);
```
%%
解答例
```js
import { sum3 } from "./libs.js";
const r = sum3(1, 10, 100);
console.log(r);
```
`libs.js`
```js
export function sum3(x, y, z) {
return x + y + z;
}
```
%%
## Mission 2
#🙂NORMAL
`./libs` 配下に以下2つのファイルがあります。
```js
// ./libs/dog.js
export function getAsJapanese() {
return "犬";
}
```
```js
// ./libs/cat.js
export function getAsJapanese() {
return "猫";
}
```
以下のコードをFIXMEコメントの要件を満たすように書き換えてください。
```js
// FIXME:"犬" と "猫" を libs配下のgetAsJapaneseから取得する
console.log(`私は犬と猫が好きです`);
```
%%
解答例
```js
import * as dog from "./libs/dog.js";
import * as cat from "./libs/cat.js";
console.log(`私は${dog.getAsJapanese()}と${cat.getAsJapanese()}が好きです`);
```
または
```js
import { getAsJapanese as dogAsJapanese } from "./libs/dog.js";
import { getAsJapanese as catAsJapanese } from "./libs/cat.js";
console.log(`私は${dogAsJapanese()}と${catAsJapanese()}が好きです`);
```
%%
## Mission 3
#😵HARD
次の説明の中で正しいものを1つ選び、他の選択肢がなぜ間違っているかも説明してください。
A. [[TypeScript]]のimport/exportに関する仕様は[[ESモジュール (JavaScript)|ESモジュール]]の仕様と同一である
B. [[Node.js]]のv22では、[[ESモジュール (JavaScript)|ESモジュール]]か[[CommonJS]]かの判定をファイルに記載されたコードから自動で判別することもできる
C. [[Deno]]は[[ESモジュール (JavaScript)|ESM]]のみをサポートしており、[[CommonJS]]には対応していない
D. ブラウザでは[[ESモジュール (JavaScript)|ESM]]によるimportは利用できないので[[バンドラー]]を使う必要がある
%%
解答例
正解はB.
A. [[TypeScript]]は[[ESモジュール (JavaScript)|ESモジュール]]の仕様を踏襲しているが、同じではない
C. [[Deno]]は[[CommonJS]]も可能な限りサポートしている
D. ブラウザは `<script type="module">` で [[ESモジュール (JavaScript)|ESM]]をサポートしている
%%
> [!hint]- Hint 1
> - [TypeScript: Documentation \- Modules](https://www.typescriptlang.org/docs/handbook/2/modules.html)
> [!hint]- Hint 2
> - [Modules: ECMAScript modules \| Node\.js v22\.14\.0 Documentation](https://nodejs.org/download/release/latest-v22.x/docs/api/esm.html#enabling)
> [!hint]- Hint 3
> - [Deno 2\.1: Wasm Imports and other enhancements](https://deno.com/blog/v2.1#better-commonjs-support)
## Mission 4
#😵HARD
[[#Mission 2]]のコードを[[CommonJS]]に変換してください。
%%
解答例
```js
// ./libs/cat.js
exports.getAsJapanese = () => "猫";
```
```js
// ./libs/dog.js
exports.getAsJapanese = () => "犬";
```
```js
const dog = require("./libs/dog.js");
const cat = require("./libs/cat.js");
console.log(`私は${dog.getAsJapanese()}と${cat.getAsJapanese()}が好きです`);
```
```json
// package.json
{
"type": "commonjs"
}
```
%%
> [!hint]- Hint 1
> - [Deno 2\.1: Wasm Imports and other enhancements](https://deno.com/blog/v2.1#better-commonjs-support)
> - [Modules: CommonJS modules \| Node\.js v22\.14\.0 Documentation](https://nodejs.org/download/release/latest-v22.x/docs/api/modules.html)
---
*NEXT* >> [[📗TDQ-BOSS3 さらばJavaScriptの世界よ]]