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 |