はじめに
この記事はNode.jsのモジュールシステムについて段階的に理解していった記録です。
基本
モジュールは以下のように読み込みます。
const http = require('http');
「モジュールってなんなんだ」ということで対話環境で叩いてみる。
{ _connectionListener: [Function: connectionListener],
METHODS:
[ 'ACL',
'BIND',
'CHECKOUT',
'CONNECT',
(中略)
Server: { [Function: Server] super_: { [Function: Server] super_: [Object] } },
ServerResponse: { [Function: ServerResponse] super_: { [Function: OutgoingMessage] super_: [Object] } },
createServer: [Function: createServer],
get: [Function: get],
request: [Function: request] }
「これは、オブジェクトか?モジュールとはオブジェクトなのだな」
Expressさん登場
Expressでは以下のようにアプリケーションを作ります。
const express = require('express');
var app = express();
「ちょっと待て」
express「はい?」
「いやお前オブジェクトのはずだろ、なんで関数呼び出しできんねん」
express「いやだって私、関数オブジェクトですから」
「なん、だと・・・。いやまあ確かにNode.jsのドキュメントにも"The module.exports property can be assigned a new value (such as a function or object)."って書いてあるわ。オッケー完全に理解した、expressは関数オブジェクトね」
express.staticの脅威
Expressで静的ファイルを提供するには以下のようにします。
app.use(express.static('public'));
「待てやこら」
express「はい?(いちいちうるせーな)」
「お前関数オブジェクトだろ、なんでメソッドっぽいことしてんねん」
express「いやまあ、Javascriptの関数オブジェクトってプロパティ設定できまして」
「まじか」
というわけで、具体的に見てみると、expressとして受け取るオブジェクト、つまり、module.exportsとして設定されているものはcreateApplication関数であり、module.exportsというかexportsが指すオブジェクトのプロパティとしてstaticが設定されています。
あれ?ていうか、bodyParserのurlencodedとjsonも設定されてるな、4.16.0からか。日本語ドキュメントしか見てなかったから気づかなかった。
まとめとあとがき
というわけで今回はNode.jsのモジュールについて見てきました。
まとめます。Node.jsのモジュールとは、
- 普通はオブジェクトでプロパティとして関数を設定する
- module.exportsに代入することで関数をモジュールのトップとすることができる
- 関数オブジェクトはプロパティを設定できるので(これはNode.jsというかJavascriptの機能)、引き続きメソッドっぽいこともできる
次にあとがき。
Pythonでも関数に属性を設定できるので、関数オブジェクト自体にプロパティが設定できるのは(上で驚いているほど)驚きではないのですが、息を吸うように普通に使われているのは驚きでした。Pythonで関数に属性設定しているのってDjangoの内部実装読んだ時にしかお目にかかっていないので。