Node.jsでモジュールを理解する:module.exportsとexportsの初心者向けチュートリアル
Node.jsにおける「module.exports」と「exports」の違い:徹底解説
Node.jsにおいて、モジュールシステムはコードを分割し、再利用性を高める重要な機能です。モジュールを定義する際に、「module.exports」と「exports」という2つのオブジェクトが使われますが、混同されやすい点も存在します。
本記事では、「module.exports」と「exports」の詳細な違いを、分かりやすくかつ網羅的に解説します。
共通点
まず、「module.exports」と「exports」は、どちらもモジュールから外部に公開する値を格納するオブジェクトです。require() 関数を使ってモジュールを読み込む際、このオブジェクトが返されます。
具体的には、以下のような値を格納できます。
- 関数
- オブジェクト
- プリミティブ値 (例:数値、文字列、ブール値)
重要な違い
一見似ている「module.exports」と「exports」ですが、実は以下の点で重要な違いがあります。
参照方法
- module.exports: モジュールのスコープ内で直接参照できます。
- exports:
exports
オブジェクト経由で参照する必要があります。
// module.exports を直接参照
module.exports = function() {
console.log('module.exports function');
};
// exports オブジェクト経由で参照
exports.myFunction = function() {
console.log('exports.myFunction');
};
書き換え可能性
- exports: 基本的には書き換えられませんが、特殊なケースを除いて書き換えることは推奨されていません。
// module.exports を書き換える
module.exports = function() {
console.log('module.exports function 1');
};
module.exports = function() {
console.log('module.exports function 2'); // 上書き
};
優先順位
モジュール内で module.exports
と exports
を同時に使用した場合、module.exports の方が優先的に使われます。
// module.exports が優先される
exports.myVar = 1;
module.exports = { myVar: 2 };
// require() で取得される値
const mod = require('./myModule');
console.log(mod.myVar); // 2が出力
使い分けの指針
上記の説明に基づき、「module.exports」と「exports」を使い分ける際の指針を以下にまとめます。
- 基本的には module.exports を使用する: 値を書き換えたり、モジュール内で直接参照したりする場合は、
module.exports
を使いましょう。 - 特殊なケースでのみ exports を使用する:
module.exports
の参照を保持する必要があるなど、特殊なケースを除いてはexports
を使用する必要はありません。
まとめ
項目 | module.exports | exports |
---|---|---|
参照方法 | モジュールのスコープ内で直接参照可能 | exports オブジェクト経由で参照 |
書き換え可能性 | 書き換え可能 | 基本的には書き換え不可(特殊なケースを除く) |
優先順位 | exports より優先 | |
使い分け | 基本的には module.exports を使用する | 特殊なケースでのみ使用する |
その他
- 歴史的に
exports
が先に使われていましたが、現在ではmodule.exports
を推奨するのが一般的です。 - コードの可読性向上のため、どちらか一方に統一して使用することが望ましいです。
これらの情報に加え、実際にコードを書いて試してみることで、より深い理解を得ることができます。
サンプルコード:module.exportsとexportsを使い分ける
基本的な使い方
// module1.js
// module.exports を使って関数を提供
module.exports = function myFunction() {
console.log('myFunction called!');
};
// module2.js
// require() でモジュールを読み込み、exports経由で関数を利用
const mod1 = require('./module1');
mod1.myFunction(); // myFunction called!が出力
module.exportsで値を書き換える
// module3.js
// module.exports で値を書き換える
module.exports = 1;
module.exports = 2;
// module4.js
// require() でモジュールを読み込み、値を取得
const mod3 = require('./module3');
console.log(mod3); // 2が出力
exportsオブジェクトにプロパティを追加
// module5.js
// exportsオブジェクトにプロパティを追加
exports.myVar = 10;
// module6.js
// require() でモジュールを読み込み、exportsオブジェクトのプロパティを利用
const mod5 = require('./module5');
console.log(mod5.myVar); // 10が出力
module.exportsとexportsを同時に使用する
// module7.js
// module.exportsとexportsを同時に使用する
exports.myVar = 20;
module.exports = {
myFunction: function() {
console.log('myFunction called!');
}
};
// module8.js
// require() でモジュールを読み込み、値と関数をそれぞれ利用
const mod7 = require('./module7');
console.log(mod7.myVar); // 20が出力
mod7.myFunction(); // myFunction called!が出力
これらのサンプルコードを通して、「module.exports」と「exports」の違いを理解し、適切に使い分けることができるようになりました。
補足
- 上記のコードはあくまで基本的な例であり、実際の開発ではより複雑なモジュール構成になる可能性があります。
- コードの可読性向上のため、コメントを適切に記述することをおすすめします。
Node.jsにおける「module.exports」と「exports」の代替方法
ES Modulesは、ブラウザやNode.jsを含むさまざまなJavaScriptランタイムで標準的にサポートされるモジュールシステムです。従来のCommonJSモジュールとは異なり、以下の利点があります。
- より簡潔な構文:
import
とexport
キーワードを使用して値をエクスポート/インポートできます。 - 依存関係の明確化:
package.json
ファイルを使用してモジュールの依存関係を宣言できます。 - ツリーシェイキング: 使用していないコードが自動的に削除されます。
ES Modulesのサンプルコード
// module.js
// ES Modulesを使って関数を提供
export function myFunction() {
console.log('myFunction called!');
}
// main.js
// import キーワードを使ってモジュールを読み込み、関数を利用
import { myFunction } from './module';
myFunction(); // myFunction called!が出力
その他の代替方法
- クラス: クラスを使って値や関数をカプセル化することができます。
- 関数: 関数オブジェクトを返して値や関数を提供することができます。
使い分け
- 既存のプロジェクト: すでにCommonJSモジュールを使用しているプロジェクトの場合は、「module.exports」と「exports」を使い続けるのが一般的です。
- 新規プロジェクト: 新規プロジェクトの場合は、ES Modulesの使用を検討することをおすすめします。
Node.jsモジュールで値をエクスポートするには、「module.exports」と「exports」以外にも、ES Modulesやクラス、関数などの方法があります。それぞれのメリットとデメリットを理解し、状況に応じて適切な方法を選択することが重要です。
javascript node.js commonjs