9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【JavaScript】モジュール

Posted at

モジュール

JavaScriptは、はじめは小さなものから始まりました。しかし。昨今のフロントエンドではJavaScriptのコードは非常に大きなものになり、グローバル変数の衝突や保守性などの問題がありました。

node.jsでは、ES2015よりも前にモジュールを分割するrequire構文が実装されていたりなどしていましたが、すでに私達はネイティブのJavaScriptでモジュール構文を使用することができます。

モジュールのルール

JavaScriptとモジュールの世界のルールは少々異なっています。

モジュール内は常にStrictモード

はじめに、コードは常にStrictモードで実行されます。
use strict構文を追加する必要はありません。

Strictモードは、そもそも下位互換性を維持して既存のアプリケーションが動かなくなることを防ぐための手段でしたが。モージュルは全く新しいコンテキストであるため、モージュルに下位互換性をもたせる必要はありません。

ルートコンテキストでのthis

もう一つの違いは、ルートコンテキストでthisが何を指すかです。
通常のJavaScriptでは、グローバルオブジェクト(ブラウザではwindow)を指しますが、モジュールでのルートコンテキストのthisundefinedです。

モジュールのexportとimport

モジュールの中に配置された変数や関数はグローバル空間を汚染しません。
モジュールの中の変数や関数を外の世界で利用するためには、export構文を使用します。
エクスポートできるものには、constletvar、関数、クラスがあります。これらは、最上位の階層にある必要があり、例えば関数内でexportすることはできません。
export構文は、デフォルトエクスポートと名前付きエクスポートがあります。

デフォルトエクスポート

デフォルトエクスポートは、1つのモジュールにつき1つしか宣言することができません。

次のように宣言します。

export default function logging() {
  // なにかログを行う
}

エクスポートされた変数や関数は、importすることでしようすることができます。

デフォルトエクスポートされたものは、インポート先で自由に名前をつけることができます。

import LogFunc from './src/log'

名前付きエクスポート

一方、名前付きエクスポートはモジュールの中で0個以上宣言することができます。
デフォルトエクスポートとの構文の違いは、defultを取り除いただけです。

export const array = [10, 20, 30, 40, 50]
export const user = {
  name: '鈴木太郎',
  age: 25
}
export const MAX_AGE = 100

名前付きエクスポートをインポートしてみます。モジュールのすべてをインポートしたい場合には、*を使用します。

import * as Utils from './src/user'

しかし、通常は必要が無いものもインポートするのは良い作法とは言えません。
通常は、次のように限定的にインポートをします。

import { user } from 'src/user`

もしもインポートする際に、名前が重複してしまうような場合には、別名をつけることができます。

import { user as defaultUser } from 'src/user`

エクスポートする際に別名を使用することもできます。

const user = {
  name: '鈴木太郎',
  age: 25
}

export { user as DefaultUser } 

動的なモジュールの読み込み

ブラウザで利用できるJavaScriptもモジュールは、常に動的にモジュールを読み込みます。つまり、モジュールが必要なときだけ読み込むようにするので、パフォーマンス上の利点があります。

これはimportを関数として実行してパラメータとしてパスを指定することができます。これは次のようにPromiseを返します。

import('src/user')
    .then(module => {
        console.log(user.name)
    })

ブラウザでモジュールを実行する

実際にモジュールを使用してみます。

フォルダの構成は次のようになっています。

index.html
module1.mjs
module2.mjs

ネイティブのJavaScriptモジュールは拡張子mjsを持つことになります。

注意: ネイティブの JavaScript モジュールは、拡張子 .mjs を持つことが重要です。なぜなら、ブラウザーは JavaScript と互換性のある MIME タイプ text/javascript を持つファイルをインポートします。この拡張子を使うことにより、 "The server responded with a non-JavaScript MIME type" のような厳密な MIME タイプのチェックエラーを避けることができます。また、.mjs という拡張子は明確さ (つまり、このファイルはモジュールであり、通常の JavaScript ではないということ) や、他のツールとの相互利用性の観点からもよいことです。Google のさらに詳細なメモも参照してください

JavaScript モジュール

それぞれのファイルの中身は以下の通りです。

index.html
<!DOCTYPE html>
<html>
<head>
	<title>module</title>
</head>
<body>
	<script type="module" src="/module1.mjs"></script>
	<script type="module" src="/module2.mjs"></script>
</body>
</html>

<script>タグにtype="module"を含めることで、そのスクリプトがモジュールであることを宣言します。

module1.mjs
export function plus(num1, num2) {
  return num1 + num2
}
modeule2.mjs
import { plus } from './module1.mjs'

console.log(plus(1, 1))

モジュールは次のようの簡単なファイル構成です。
これをローカルでテストしようとするとき、file://URLを使ってHTMLファイルを読み込もうとすると、CORSエラーが発生することに注意してください。

スクリーンショット 2020-04-13 11.28.29.png

VSCode拡張のLiveServerを使用すると、簡単にローカルサーバーを建てることができます。
モジュールの読み込みに成功していることが確認できました。

スクリーンショット 2020-04-13 11.30.53.png

参考

JavaScript モジュール
入門JavaScriptプログラミング

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?