モジュールとは
ソースコードを機能毎に分割してメンテナンスしやすくする仕組み。
代表的なものとして下記二つがある
- CJS(CommonJS)
- ESM(ES Modules)
CommonJSとは
Node.js上でモジュールを管理する仕組み。
require / exportsというキーワードを使ってモジュールの読み込みや外部ファイルへの露出を行う。
ES Modulesとは
ECMAScriptの仕様に基づくモジュール管理システム。主にブラウザ側で使用。
import / exportというキーワードを使ってモジュールの読み込みや外部ファイルへの露出を行う。
ES Modulesの規格でexportされたものはES Modulesの規格でimportする必要があり、CommonJSの規格でexportsされたものはCommonJSの規格でrequireする必要がある。この二つのモジュールシステムを跨いでそれぞれのキーワードを使うことはできない。
ES Modulesの読み込みにはscriptタグのtype属性をmodule
にする
比較
ES Modules | CommonJS | 備考 | |
---|---|---|---|
読み込み / 露出キーワード | import / export | require / exports | - |
使用される場所 | Browser | Node.js | ES ModulesはNode.js上でも動かせるが有効にするための条件がある |
拡張子 | .mjs | .cjs | js拡張子で問題ないが、どちらの仕組みで動いているのか明示的に分かるように、拡張子を分けている場合がある |
ES Modulesの基本的なimport / export
exportしたいファイルmodulaA.js
/**
* exportしたい変数、関数の前にexportを記述
*/
export let publicVal = 0;
export function publicFn() {
console.log('publicFn called: ')
}
//もうひとつ、exportする方法としてdefaultキーワードを使用したものがある
export default 1; //このdefaultに続く値が、このモジュールのデフォルトでexportされる値になる。
importしたいファイルmodulaB.js こちらを読み込ませる 例)<script type="module" src="moduleB.js"></script>
/**
* importする方法として、
* import { exportされている変数名や関数名 } from "読み込む先のファイルを指定"
* exportだけのものは必ず上記のように{}をつけて、importを行う。
* defaultキーワードでexportされているものは任意の名前で定義してimportする。{}はいらない。
* defaultキーワードを使ってexportされたものとそれ以外をimportするときはカンマ区切りで記述できる
* 例)import defaultVal, { publicVal as val, publicFn as fn } from "./moduleA.js";
*/
//import { publicVal, publicFn } from "./moduleA.js"; //webpackなどモジュールを一つのファイルにまとめてくれるソフトを使うと.jsは省略できる場合がある。使っていない場合は拡張子まで必ずかく。
import defaultVal, { publicVal as val, publicFn as fn } from "./moduleA.js"; //このように as 変更後の名前 の形で、このファイル内でのみ使用できる名前を定義することができる
console.log(val);
fn();
console.log(defaultVal);
/**
* 下記のように*を使った記述をするとオブジェクトの形で格納される
* import defaultVal, * as moduleA from './moduleA.js';
* console.log(moduleA.publicVal);
*/
モジュールコンテキストとモジュールスコープ
ES Modulesを使用した場合、グローバルコンテキストがモジュールコンテキストに切り替わる。
基本的にグローバルコンテキスト、モジュールコンテキストも挙動は似ている。
グローバルコンテキストでthisを使用した場合、グローバルオブジェクト(window)が参照できるが、モジュールコンテキストの場合は、thisが使用できない。
ES Modulesを使用した場合、スクリプトスコープがモジュールスコープに切り替わる。
console.log(this);// -> undefined
function fn() {
console.log(this);
}
fn();// -> undefined
const obj = {
fn
}
obj.fn();// -> オブジェクトのメソッドとして呼び出す場合など、モジュールコンテキスト以外であればthisは使用できる。
モジュールの特徴
type属性'module'はデフォルトでdefar属性が付与され、
htmlの構文解析が終わったタイミングでscriptが実行される非同期的な処理となる。
一度読み込まれると、同じものは読み込まれない。
nomodule属性を付与するとモジュールに対応していないブラウザにのみ、そのscriptタグが読み込まれる。
モジュールの場合は常にstrictモード
strictモードとは
通常のJavaScriptで許容されている一部の書き方を制限する方法。従来のjs記法ではバグにならなかったものもエラー表示してくれることで、意図しないバクの混入、予約語の確保、コードのセキュア化などのメリットがある。
ファイルの先頭、もしくは関数内の先頭行にuse strict
の記述するとStrictモードが有効化される。
そのstrictモードがモジュールの場合では常に有効化されていて、上記記述をする必要がない。
参考