Node.jsのexportsについて
(https://numb86-tech.hatenablog.com/entry/2016/07/20/202744)
Node.jsにはモジュール機能があり、他のファイルの内容を読み込むことが出来る。
だが、何となくでしか使い方を理解していなかったので、調べてみた。
このエントリのコードは全て、v4.4.3で動かした。
基本
まず、呼び出される側のファイルで、モジュール化する値やオブジェクトをexportsしておく。
そうすることで、その値やオブジェクトに外部からアクセスすることが可能になる。
呼び出す側ではrequire()関数を使い、ファイルを読み込む。
読み込んだファイルから、exportsされている値やオブジェクトにアクセスできるようになる。
ファイルを読み込んでも、exportsされていない値(上記のケースではfoo)には、アクセス出来ない。
下記のような書き方も出来る。
module.exportsとexports
module.exportsとexportsという書き方が出てきた。
何が違うのだろうか。
ネットで軽く調べた限り、同じものとして扱って構わないらしい。
という図式であり、exportsはmodule.exportsを参照している、らしい。
だから、
という書き方をしていれば、exports = module.exportsの図式は壊れない。
だが例えば、module.exportsに新しくオブジェクトを割り当ててしまうと、exports = module.exportsのリンクは途切れてしまう。
それにより、以下の様な挙動が発生する。
なぜvalueがundefinedになってしまうのかと言えば、module.exportsに新しくオブジェクトを割り当ててしまい、リンクが途切れ、module.exportsとexportsはそれぞれ別のものに指すようになってしまったから。
parst.jsを実行させてみることで、そのことが確認出来る。
元々両者は同じものを指していたが、module.exportsの再定義によってそれが変わってしまっている。
そして、require()で読み込むのは、読み込んだファイルのmodule.exportsである。
そのため、この状態では、exportsにいくら値を設定しても、外部ファイルがそれを呼び出すことは出来ない。
まとめると、
module.exportsというオブジェクトを、require()によって外部ファイルが呼び出すことが出来る- 初期状態では、
exportsはmodule.exportsを参照しており、両者は同じものを指している
ということになる。
require()すると、対象となるファイルの中身が実行される
require()は、ただ単にmodule.exportsを取得するだけでなく、そのファイルの中身を実行する。
ファイルの中身を実行してmodule.exportsを返す、というのがrequire()の挙動のようだ。
注意点として、require()は、同じファイルに対しては1度しか実行されないようだ。
そのため上記のケースでは、2回目のrequire()では何も表示されなかった。
require()の結果を別の変数に割り当てようとしても同様。require()自体が1度しか実行されない。
この、「require()は同一ファイルに対して1度のみ実行され」、「その結果は記憶されている」という仕様により、次のような特徴が生まれる。
クロージャ
記述の通り、module.exportsというオブジェクトに入っていない値は、呼び出せない。
しかし、module.exportsを通して間接的にアクセスすることは出来る。
上記の例では、エクスポートされているのはmyFuncのみ。だから、エクスポートされていないintにアクセスしようとしてもundefinedになる。
しかしmyFuncにおいてintを使っているため、myFuncを通じて間接的にアクセスできる。
エクスポートしていなくても、必要に応じて値を読みに行く。これは、関数やオブジェクトでも同様である。
showResult()の中で、エクスポートされていないadd()が使われているが、問題なく動く。
だが、add()そのものがpartsに入っているわけではない。あくまでも、必要になった時(この場合はshowResult()実行時)に呼び出されるだけである。
この特徴を利用すると、クロージャのような仕組みを作ることが出来る。
変数intはエクスポートされていないため、それに直接アクセスすることは出来ない。
だが、関数get()やincrement()を通して、操作、取得することが出来る。
ディレクトリ
require()の引数にディレクトリを渡すことも出来る。
そうすると、そのディレクトリのindex.jsを読み込む。
その時、index.jsで他のファイルを読み込みエクスポートしておくことで、複数のファイルを簡単に読み込める。
このような状況では、以下の様な書き方をすることで、data.jsやcal.jsにアクセスすることが出来る。
参考記事
'C Lang > JS Technic' 카테고리의 다른 글
| generator 객체2(JavaScript の ジェネレータ を極める!) (0) | 2018.05.14 |
|---|---|
| generator 객체1 (function *, next(), yield, promise와 yield,co모듈과 yield) (0) | 2018.05.14 |
| nodejs의 log모듈 :log4js-node(이 모듈은 뭘까, 이 모듈로 뭐가 가능한거야, 예로 보자 ) (0) | 2018.05.13 |
| nodejs에서 초기설정 파일을 불러오는 방법 : config 모듈 사용하기 (0) | 2018.05.13 |
| var, let, const 차이점 (0) | 2018.05.08 |