web-dev-qa-db-ja.com

node.jsのrequire()はどのように機能しますか?

私はこれを試しました:

// mod.js
var a = 1;
this.b = 2;
exports.c = 3;

// test.js
var mod = require('./mod.js');
console.log(mod.a);    // undefined
console.log(mod.b);    // 2
console.log(mod.c);    // 3, so this === exports?

だから私はrequire()がこのように実装されるかもしれないことをイメージします:

var require = function (file) {
    var exports = {};
    var run = function (file) {
        // include "file" here and run
    };
    run.apply(exports, [file]);
    return exports;
}

そうですか? require()を理解するのを手伝ってください、またはどこでソースコードを見つけることができます。ありがとう!

70
Trantor Liu

ソースコードは here です。 exports/requireはキーワードではなく、グローバル変数です。あなたのメインスクリプトは、そのコンテキストにrequireprocessなどのすべてのグローバルを含む関数の 開始 の前に ラップ です。

Module.js自体はrequire()を使用していますが、これは別のrequire関数であり、「node.js」というファイルでは defined です。

上記の副作用:モジュールの中央に(関数に属さない)「return」ステートメントを置いて、残りのコードを効果的に「コメントアウト」するのは完全に問題ありません

50
Andrey Sidorov

Andrey はソースコードを示しましたが、使用方法についても疑問がある場合は、簡単で簡単な説明がここにあります( http://nodejs.org/api/modules.html =)。

これらは私にとって2つの良い例でした。

//foo.js, multiple methods
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

//circle.js
var PI = Math.PI;
exports.area = function (r) {
  return PI * r * r;
};
exports.circumference = function (r) {
  return 2 * PI * r;
};

//bar.js
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());

//square.js, single method
module.exports = function(width) {
  return {
    area: function() {
      return width * width;
    }
  };
}

私の好きなパターンは

(function (controller) {

  controller.init = function (app) {

    app.get("/", function (req, res) {
        res.render("index", {});
    });

  };
})(module.exports);
8
Andy
var mod = require('./mod.js');

Requireは、pathと呼ばれる1つの引数を取る関数です。この場合、パスは./mod.jsです

requireが呼び出されると、一連のタスクが発生します:

  1. lib/module.js で宣言されたModule.prototype.require関数を呼び出します。これは、パスが存在し、文字列であることをアサートします

  2. Module._resolveFilename(request, parent, isMain)を介してファイルを解決する lib/module.js の関数であるModule._loadを呼び出します。

  3. Module._resolveFilename関数が呼び出され、モジュールがネイティブかどうかが確認されます(ネイティブモジュールは lib/internal/bootstrap_node.js で定義されているNativeModule関数によって返されます)、はいの場合モジュールを返します。そうでない場合は、parhの文字数(少なくとも2文字)といくつかの文字(パスは./で始まる必要があります)をチェックします/lib/internal/bootstrap_node.js で定義されているModule._resolveLookupPaths関数経由
  4. ファイルを含むディレクトリを確認してください
  5. パスに拡張子が含まれる場合(この例ではyes:mod.js)、 lib/path.js で定義されているbasename関数は、拡張子が「 js」であることを確認します "
  6. 次に、引数var module = new Module(filename, parent);で指定されたファイルの新しいモジュールを作成します
  7. コンテンツは、 lib/internal/bootstrap_node.js で定義されている関数NativeModule.prototype.compileを介してv8を介してコンパイルされます
  8. lib/internal/bootstrap_node.js で定義されているNativeModule.wrapは、mod.jsでコンパイルされたjavascriptコンテンツを受け取り、それをラップします。このすべてを機能させる他のコードでラップします。したがって、mod.jsで記述したコードは関数式でラップされます。つまり、ノードに書き込むものはすべてV8で実行されます
  9. module.exportsが返されます
6