これは、Pascal Prechtのブログ投稿のおかげで、違いを理解するのに役立ちました。
サービスは、名前とサービスを定義する関数を使用するモジュールのメソッドです。その特定のサービスを注入して、コントローラー、ディレクティブ、フィルターなどの他のコンポーネントで使用できます。ファクトリーはモジュールのメソッドであり、ファクトリーを定義する名前と関数も受け取ります。また、サービスで行ったのと同じように注入して使用することもできます。
newで作成されたオブジェクトは、コンストラクター関数のprototypeプロパティの値をプロトタイプとして使用するため、Object.create()を呼び出すAngularコードを見つけました。これは、インスタンス化されたときにサービスコンストラクター関数であると考えています。ただし、ファクトリ関数は実際には呼び出される関数にすぎないため、ファクトリのオブジェクトリテラルを返す必要があります。
これは私が工場で見つけた角度1.5コードです:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
factory()関数のAngularソースコードスニペット:
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
これは、渡された名前とファクトリー関数を受け取り、ファクトリー関数である$ getメソッドを持つ同じ名前のプロバイダーを返します。インジェクターに特定の依存関係を要求するときはいつでも、基本的に$ get()メソッドを呼び出すことにより、対応するプロバイダーにそのサービスのインスタンスを要求します。そのため、プロバイダーを作成するときに$ get()が必要です。
以下は、サービス用の角度1.5コードです。
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
service()を呼び出すと、実際にはfactory()が呼び出されることがわかります。ただし、サービスコンストラクター関数をそのままファクトリーに渡すだけではありません。また、指定されたコンストラクターによってオブジェクトをインスタンス化するようインジェクターに要求する関数も渡します。
言い換えると、MyServiceをどこかに挿入すると、コード内で次のことが起こります。
MyServiceProvider.$get(); // return the instance of the service
再度述べると、サービスはファクトリを呼び出します。ファクトリは、対応するプロバイダーの$ get()メソッドです。さらに、$ injector.instantiate()は、コンストラクター関数を使用して最終的にObject.create()を呼び出すメソッドです。これが、サービスで「this」を使用する理由です。
ES5の場合、service()またはfactory()のどちらを使用するかは関係ありません。サービスのプロバイダーを作成するために呼び出されるのは常にファクトリです。
サービスでもまったく同じことができます。サービスはコンストラクタ関数ですが、オブジェクトリテラルを返すことを妨げるものではありません。そのため、サービスコードを取得して、基本的にはファクトリとまったく同じように記述できます。つまり、オブジェクトを返すファクトリとしてサービスを記述できます。
ほとんどの人がサービスよりも工場の使用を勧めるのはなぜですか?これは、Pawel Kozlowskiの本「AngularJSを使用したWebアプリケーション開発の習得」から得られた、私が見た中で最高の答えです。
ファクトリーメソッドは、オブジェクトをAngularJS依存性注入システムに取り込む最も一般的な方法です。非常に柔軟で、高度な作成ロジックを含めることができます。ファクトリは通常の関数であるため、「プライベート」変数をシミュレートするために新しい字句スコープを利用することもできます。特定のサービスの実装の詳細を隠すことができるので、これは非常に便利です。」