Javascript_javascript スキルにおける依存関係の挿入についての深い理解
遅かれ早かれ、他の開発者の抽象化を使用する必要があります。つまり、他の人のコードに依存することになります。依存関係のない (依存関係のない) モジュールが望ましいですが、それを実現するのは困難です。あなたが作成する素晴らしいブラック ボックス コンポーネントであっても、多かれ少なかれ何かに依存しています。ここで依存性注入が登場します。依存関係を効果的に管理する機能は、今や絶対的に必要なものになっています。この記事では、この問題についての私の調査とその解決策のいくつかを要約します。
1. 目標
2 つのモジュールがあると想像してください。 1 つ目は Ajax リクエスト サービス (サービス) を担当し、2 つ目はルーティング (ルーター) を担当します。
var service = function() {
return { name: 'Service' };
}
var router = function() {
return { name: 'Router' };
}
別の関数がありますこれら 2 つのモジュールに使用します。
var doSomething = function(other) {
var s = service();
var r = router();
};
見た目をさらに面白くするために、この関数は 1 つのパラメーターを受け入れます。もちろん、上記のコードを完全に使用することはできますが、明らかに十分な柔軟性がありません。 ServiceXML または ServiceJSON を使用したい場合、またはテスト モジュールが必要な場合はどうすればよいでしょうか。関数本体を編集するだけでは問題を解決できません。まず、関数のパラメーターを通じて依存関係を解決できます。つまり、
var doSomething = function(service) , router, other ) {
var s = service();
var r = router();
};
追加のパラメータを渡すことで目的を達成しますが、これは新たな問題をもたらすことになる。 doSomething メソッドがコード全体に散在している場合を想像してください。依存関係を変更する必要がある場合、関数を呼び出すすべてのファイルを変更することはできません。
これを行うのに役立つツールが必要です。これは依存関係注入が解決しようとしている問題です。依存関係注入ソリューションが達成すべき目標をいくつか書き留めてみましょう:
依存関係を登録できるはずです
1. インジェクションは関数を受け取り、必要な関数を返す必要があります
2. あまり多くを書くことはできません - 合理化された美しい構文が必要です
3 .インジェクションは渡された関数のスコープを維持する必要があります
4. 渡された関数は依存関係の説明だけでなくカスタムパラメータを受け入れることができる必要があります
5. これは完璧なチェックリストです。
3. RequireJS/AMD メソッド
RequireJS について聞いたことがあるかもしれませんが、これは依存関係の注入を解決するための良い選択です。
define(['service', 'router ']、関数(サービス、ルーター) {ここでのパラメータの順序は重要です。上で述べたように、同じ構文を受け入れる injector というモジュールを作成しましょう。
コードをコピー
});
doSomething("Other");
すべきだdoSomething 関数本体の内容を明確に説明するために、少し TDD (テスト駆動開発) メソッドを反映して、作成したコードが期待どおりに動作することを確認するために、expect.js (アサーション ライブラリ) を使用します。
インジェクター モジュールから始めましょう。これは優れたシングルトン パターンなので、プログラムのさまざまな部分でうまく機能します。
コードをコピー
var injector = {
依存関係: {},
register: function(key, value) {
this.dependency[key] = value;
},
解決: function(deps, func,scope) {
}
}
これは、プロパティを保存するための 2 つのメソッドを備えた非常に単純なオブジェクトです。私たちが行うことは、deps 配列をチェックし、依存関係変数で答えを検索することです。残っているのは、.apply メソッドを呼び出して、前の func メソッドから引数を渡すことだけです。
resolve: function(deps, func,scope ) {
var args = [];
for(var i=0; i
args.push (this.Dependency [d]);
} else {
新しいエラーをスロー ('解決できません' d);
func.apply(scope || {}, args.concat(Array.prototype.slice.call(arguments, 0)));
}
}
スコープはオプションです はい、Array.prototype.slice.call(arguments, 0)引数変数を実数配列に変換するには必要です。ここまでは順調ですね。私たちのテストは合格しました。この実装の問題は、必要な部分を 2 回記述する必要があり、その順序を間違えることができないことです。追加のカスタム パラメーターは常に依存関係の後に来ます。
Wikipedia の定義によれば、リフレクションとは、実行時にオブジェクトの構造と動作を検査および変更するプログラムの機能を指します。簡単に言えば、JavaScript のコンテキストでは、これは特にオブジェクトまたは関数のソース コードを読み取って分析することを指します。記事の冒頭で述べた doSomething 関数を完成させましょう。 doSomething.tostring() をコンソールに出力した場合。次の文字列を取得します:
}"
このメソッドによって返される文字列は、次の機能を提供します。パラメータを走査すること、そしてさらに重要なことに、パラメータの名前を取得できることです。これは実際に、Angular が依存関係の注入を実装する方法です。私は少し怠け者だったので、Angular コードのパラメータを取得するための正規表現を直接インターセプトしました。
deps = func.toString().match(/^functions*[^(]*(s*([^)]*))/m)[1].replace(/ /g, '').split (',');
スコープ = argument[1] {};
return function() {
var a = Array.prototype.slice.call(arguments, 0) );
for(var i=0; i
args.push(self.dependency[d] && d != ' ' ? self.dependency [d]: a.shift());
}
func.apply(scope || {}, args);
}
}
正規表現を実行します。 other)", "service, router, other"]
の結果
必要なのは 2 番目の項目だけのようです。スペースをクリアして文字列を分割すると、deps 配列が得られます。大きな変更点は 1 つだけです:
var a = Array.prototype .slice.call(arguments, 0);
...
args.push(self.dependency[d] && d != '' ? self.dependency[d] : a. SHIFT());
依存関係配列をループし、欠落している項目が見つかった場合は引数オブジェクトから取得しようとします。ありがたいことに、配列が空の場合、shift メソッドはエラーをスローするのではなく、単に未定義を返します (Web のアイデアのおかげです)。新しいバージョンのインジェクターは次のように使用できます:
var doSomething = injector.resolve(function(service, other, router) {
Expect(service().name).to.be('Service');
Expect(router().name ).to.be( 'ルーター');
Expect(other).to.be('その他');
});
doSomething("その他");
依存関係を書き直す必要はなく、順序が崩れる可能性があります。それは今でも機能しており、Angular の魔法を再現することに成功しました。
しかし、このアプローチは完璧ではなく、反射型注射では非常に大きな問題となります。圧縮するとパラメーター名が変更され、正しいマッピングを維持できなくなるため、ロジックが壊れます。たとえば、 doSometing() は圧縮すると次のようになります:
var doSomething=function(e,t,n){var r=e();var i=t()}
Angular チームが提案した解決策は次のようになります:
var doSomething = injector.resolve(['service', 'router', function(service, router) {
}]);
これは、最初のソリューションとよく似ています。より良い解決策が見つからなかったので、2 つのアプローチを組み合わせることにしました。以下はインジェクターの最終バージョンです。
var injector = {
依存関係: {},
register: function(key, value) {
this.dependency[key] = value;
},
solve: function() {
var func, deps,scope , args = [], self = this;
if(引数の種類[0] === 'string') {
func = argument[1];
deps = argument[0].replace( / /g , '').split(',');
スコープ = 引数[2] || {};
} else {
func = argument[0];
deps = func.toString ().match(/^functions*[^(]*(s*([^)]*))/m)[1].replace(/ /g, '').split(',' );
スコープ = 引数[1] i=0; i
var d = deps[ i]; : a.shift());
解決ビジターは 2 つまたは 3 つのパラメーターを受け入れます。パラメーターが 2 つある場合、実際にはこの記事で前述したものと同じです。ただし、パラメータが 3 つある場合は、最初のパラメータが変換され、deps 配列が埋められます。テスト例は次のとおりです:
var doSomething = injector.resolve('router,,service', function(a, b, c) {
Expect(a().name) ).to .be('Router');
Expect(b).to.be('Other');
Expect(c().name).to.be('Service');
} );
doSomething("Other");
最初のパラメータの後にカンマが 2 つあることに気づくかもしれませんが、これはタイプミスではないことに注意してください。 null 値は実際には「Other」パラメータ (プレースホルダ) を表します。これは、パラメーターの順序を制御する方法を示しています。
5. スコープを直接注入する
操作関数 (つまり this オブジェクト) のスコープに関係する 3 番目の注入変数を使用することがあります。したがって、多くの場合、この変数を使用する必要はありません。
var injector = {
依存関係: {},
register: function(key, value) {
this.dependency[key] = value;
},
solve: function(deps, func,scope) {
var args = [ ];
スコープ = スコープ {};
for(var i=0; i
scope[d] = this.dependency[d]; }
return function() {
func.apply(scope || {}, Array.proto type.slice.call(引数、0)); スコープに依存関係を追加するだけです。この利点は、開発者が依存関係パラメーターを記述する必要がなくなり、依存関係パラメーターがすでに関数スコープの一部になっているということです。
コードをコピー

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScript は Web 開発で広く使用されているプログラミング言語であり、WebSocket はリアルタイム通信に使用されるネットワーク プロトコルです。 2 つの強力な機能を組み合わせることで、効率的なリアルタイム画像処理システムを構築できます。この記事では、JavaScript と WebSocket を使用してこのシステムを実装する方法と、具体的なコード例を紹介します。まず、リアルタイム画像処理システムの要件と目標を明確にする必要があります。リアルタイムの画像データを収集できるカメラ デバイスがあるとします。

Go では、依存関係注入 (DI) モードは、値の受け渡しやポインターの受け渡しなど、関数パラメーターの受け渡しを通じて実装されます。 DI パターンでは、依存関係は通常、分離を改善し、ロック競合を軽減し、テスト容易性をサポートするためにポインターとして渡されます。ポインターを使用すると、関数はインターフェイスの種類にのみ依存するため、具体的な実装から切り離されます。また、ポインターの受け渡しにより、大きなオブジェクトを渡す際のオーバーヘッドが削減されるため、ロックの競合が軽減されます。さらに、DI パターンでは依存関係を簡単にモックできるため、DI パターンを使用した関数の単体テストを簡単に作成できます。
