現在、あらゆるフレームワークがモジュール化されており、フロントエンドの JavaScript も例外ではありません。各モジュールは特定の機能を担当しており、モジュール間には相互依存関係があるため、JavaScript で依存関係の注入を実装するにはどうすればよいかという疑問が生じます。 (JavaScript の依存関係の注入、すべての主要なフレームワークには対応する実装があります。ここでは実装のアイデアのみを学習します)
以下の要件:
定義済みのサービス モジュールの Key-Value コレクションが既に存在すると仮定します。func は追加された新しいサービスであり、サービスの依存関係のパラメータ リスト。
var services = { abc : 123, def : 456, ghi : 789 }; // 何らかの Service が定義されていると仮定します
function Service(abc, ghi){ this.write = function(){ console.log(abc); console.log(ghi); } } function Activitor(func){ var obj; // 实现 return obj; }
解決策:
何らかのメカニズム (反映?) を通じて、 funcで定義されたパラメータリストには一つずつ値が代入されます。次に、何らかのメカニズム (Activitor?) を通じて関数をインスタンス化します。
解決策:
1. func のパラメータリストを取得します:
パラメータリストを取得するには?最初に思い浮かぶのは、反射メカニズムです。では、JavaScript にはリフレクションがあるのでしょうか?現時点では eval(str) 関数の使い方しか分かりませんが、パラメータリストを取得するための適切な実装はないようです。 func.arguments の定義をもう一度見てみると、このプロパティは func が呼び出されてパラメータが渡された場合にのみ有効であり、要件を満たすことができません。
func.toString()の後の文字列を処理してパラメータリストを取得できますか?
試してみましょう:
function getFuncParams(func) { var matches = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); if (matches && matches.length > 1) return matches[1].replace(/\s*/, '').split(','); return []; };
これで、 func パラメーターのリスト配列を取得できます。
2. パラメーター リストに基づいて依存関係を検索します。
パラメーター リストを取得した後、つまり依存関係リストを取得した後、依存関係をパラメーターとして渡すのは非常に簡単です。
var params = getFuncParams(func); for (var i in params) { params[i] = services[params[i]]; }
3. 依存関係パラメーターを渡してインスタンス化します:
JavaScript に func.constructor があることがわかっており、call(thisArg,[arg[,arg,[arg,[…]]]]) と apply( ThisArg 、args...) どちらの関数もインスタンス化 func 操作を実装できます。 call 関数の最初のパラメータはこのポインタで、残りはパラメータ リストです。これは func パラメータ リストがわかっている場合に使用するのに適していますが、私のニーズには合いません。 2番目のapply関数を見ると、最初のパラメータもこのポインタであり、2番目のパラメータはパラメータ配列です。呼び出されると、関数のパラメータリストに値が1つずつ自動的に割り当てられます。これはちょうど私の条件を満たすものです。ニーズ。
コードはおおよそ次のとおりです:
function Activitor(func){ var obj = {}; func.apply(obj, params); return obj; }
この時点で、関数のインスタンスを作成し、関数に必要なパラメーターを渡すことができます。
4. 印刷してテストします:
完全なコード:
var // 假设已定义好某些Service services = { abc: 123, def: 456, ghi: 789 }, // 获取func的参数列表(依赖列表) getFuncParams = function (func) { var matches = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); if (matches && matches.length > 1) return matches[1].replace(/\s+/, '').split(','); return []; }, // 根据参数列表(依赖列表)填充参数(依赖项) setFuncParams = function (params) { for (var i in params) { params[i] = services[params[i]]; } return params; }; // 激活器 function Activitor(func) { var obj = {}; func.apply(obj, setFuncParams(getFuncParams(func))); return obj; } // 定义新Service function Service(abc, ghi) { this.write = function () { console.log(abc); console.log(ghi); } } // 实例化Service并调用方法 var service = Activitor(Service); service.write();
コンソールは正常に印刷されます。