tl;dr: いいえ。
なぜこれが不可能なのかを理解するには、Node が舞台裏で何をしているのかを理解することが重要です。
test.js で関数を定義するとしましょう:
function foo() {
var msg = 'Hello world';
console.log(msg);
}
従来のブラウザー JavaScript では、その関数宣言をファイルに入れ、そのファイルを<script>
タグでプルするだけfoo
で、グローバル スコープで宣言されていました。
ノードは、ファイルの場合とは異なる動作をrequire()
します。
まず、やや複雑な一連のルールに基づいて、ロードするファイルを正確に決定します。
ファイルが JS テキスト (コンパイル済みの C++ アドオンではない) であると仮定すると、Node のモジュール ローダーはファイルの内容を取得するために呼び出します。 fs.readFileSync
ソース テキストは無名関数でラップされます。test.js は実際には次のようになります。
(function (exports, require, module, __filename, __dirname) {
function foo() {
var msg = 'Hello world';
console.log(msg);
}
});
これは、独自のコードを無名関数式でラップして、変数がブラウザーのグローバル スコープに漏れないようにしたことがある人なら誰でも知っているはずです。また、ノードの「魔法の」変数がどのように機能するかについても理解し始める必要があります。
モジュール ローダーは、手順 3 のソース テキストをeval
s 1に渡し、結果の無名関数を呼び出して、新しいexports
オブジェクトを渡します。( を参照してくださいModule#_compile
。)
1 - Really 、呼び出し元のスコープにアクセスできないことを除いてvm.runInThisContext
似ていますeval
無名ラッパー関数が戻った後、 の値がmodule.exports
内部的にキャッシュされ、 によって返されrequire
ます。require()
(キャッシュされた値を返すための後続の呼び出し。)
ご覧のとおり、Node はファイルのソース コードを無名関数でラップするだけで「モジュール」を実装します。したがって、JavaScript は関数の実行コンテキスト(関数のローカル変数のコレクション)への直接アクセスを提供しないため、関数をモジュールに「インポート」することはできません。
つまり、関数のローカル変数をループする方法はありません。また、オブジェクトのプロパティでできるように、任意の名前でローカル変数を作成する方法もありません。
たとえば、オブジェクトを使用すると、次のようなことができます。
var obj = { key: 'value' };
for (var k in obj) ...
obj[propertyNameDeterminedAtRuntime] = someValue;
しかし、関数のローカル変数を表すオブジェクトはありません。これは、オブジェクトのプロパティ (exports
モジュールの など) を関数のローカル スコープにコピーするために必要です。
あなたが行ったことは、を使用して現在のスコープ内でコードを生成することですeval
。生成されたコードは、キーワードを使用してローカル変数を宣言し、それが呼び出されvar
たスコープに挿入されます。eval
呼び出しをモジュールの外に移動する方法はありません。移動するeval
と、挿入されたコードが別のスコープに挿入されるためです。JavaScript には静的スコープがあるため、関数をレキシカルに含むスコープにしかアクセスできないことに注意してください。
もう 1 つの回避策は を使用することですwith
が、使用は避けてくださいwith
。
with (require('./paco.js')) {
between(start(), content(), end())
}
with
次の 2 つの理由から使用しないでください。
- V8 は名前検索の最適化を実行できないため、パフォーマンスが完全に低下します。
- 非推奨であり、厳密モードでは禁止されています。
正直に言うと、 でトリッキーなことをするのではなくeval
、将来のメンテナーに有利に働き、モジュールのエクスポートをローカル変数に割り当てるという標準的な方法に従うことをお勧めします。
頻繁に入力する場合は、1 文字の名前にします (または、より優れたエディターを使用します)。