ソフトウェア開発モデルとしてのシングル モードは、多くのオブジェクト指向言語で広く使用されていますが、JavaScript 言語には独自のオブジェクト指向アプローチがあるため、シングルモードの考え方では一部の従来のオブジェクト指向言語と一致していますが、実装にはまだ違いがあります。
まず、従来のオブジェクト指向言語におけるシングルトン パターンの定義を見てみましょう。シングルトン パターンは、一度だけインスタンス化でき、既知のアクセス ポイントを介してアクセスできるクラスです。この定義には、従来のオブジェクト指向言語の特性、つまりクラスとインスタンス化を強調する 2 つの点があります。したがって、従来のオブジェクト指向言語の場合、シングルトン モードはクラスとインスタンス化の自然な特性に基づいています。キーを使用する クラスという単語は、 new キーワードを通じてインスタンス化できるクラスを定義しますが、 new によってインスタンス化されるたびに同じインスタンスが取得されるようにする必要があります。そうしないと、そのコンストラクターは new を通じて 1 回しか呼び出すことができません。
JavaScript のシングルトン モードの定義を見てみましょう。シングルトンは、名前空間を分割し、関連するメソッドとプロパティのグループを編成するために使用されるオブジェクトです。インスタンス化できる場合は、メルトのみがインスタンス化されます。一度。上記の定義を比較すると、ここでの単一の定義は、従来のオブジェクト指向言語のクラスではなく、本質的にオブジェクトとして定義されていることがわかります。これは、JavaScript 言語がオブジェクトに基づいていることも示しています。同時に、インスタンス化できる場合、JavaScript で単一のオブジェクトを定義する方法が複数あるはずであることが後で指摘されました。 new キーワードを使用して単一のオブジェクトを作成する方法は 1 つまたは複数あります。ただし、このメソッドは JavaScript 自体の自然な機能ではありません。new キーワードを使用して作成されたオブジェクトは実際に関数を使用してコンストラクターの定義をシミュレートするためです (ES6 では class キーワードのサポートが開始されていますが、まだ参照されていません (広くサポートされています)すべてのブラウザで))、では、JavaScript の自然な機能を使用してシングルトン モードを実装するにはどうすればよいでしょうか?
var Singleton={ attribute1:true, attribute2:10, method1:function(){ }, method2:function(arg){ } }
ここでは、いくつかのプロパティとメソッドを含むオブジェクト Singleton が定義されています。このオブジェクトは、js のロード時に作成され、ページとして呼び出されます。がロードされ、js の解析と実行プロセスが完了すると、このオブジェクトのインスタンス化に new キーワードは使用されません。これは、JavaScript でのシングル モードの実装と従来のオブジェクト指向言語の大きな違いでもあります。この方法の方がシンプルでわかりやすいです。ただし、この方法にはいくつかの欠点があります。明らかな欠点の 1 つは、名前空間が提供されていないことです。他のプログラマがページ内でシングルトン変数を定義する場合、単一のオブジェクトを簡単に書き換えて混乱させることができるため、この問題を解決するには書き換えます。それは次のようになります:
var mySpace={}; mySpace.Singleton={ attribute1:true, attribute2:10, method1:function(){ }, method2:function(arg){ } }
ここでは、最初に mySpace 名前空間を定義し、次にこのオブジェクトの下に Singleton オブジェクトをマウントします。これにより、他のプログラマーがグローバル スコープ内にある場合でも、競合や誤操作の可能性が大幅に減少します。これにより、前の定義で述べたように、名前空間を分割し、関連するプロパティとメソッドをまとめて編成する機能が実現されます。
このメソッドにはまだ欠点があります。この単一オブジェクトのすべてのプロパティとメソッドは共通であり、いつでも外部からアクセスして変更できます。そのため、次のようにクロージャを使用してプライベート プロパティとメソッドをシミュレートします。
mySpace.Singleton=(function(){ var privateAttribute1=false; var privateAttribute1=[1,2,3]; function privateMethod1(){ } function privateMethod2(){ } return { publicAttribute1:true, publicAttribute2:10, publicMethod1:function(){ privateAttribute1=true; privateMethod1(); }, publicMethod2:function(arg){ privateAttribute1=[4,5,6]; privateMethod2(); } } })();
ここでは、匿名の自己実行関数を単一のオブジェクトに直接割り当てます。この関数では、var キーワードと function キーワードを使用して、そのプライベート プロパティとメソッドをそれぞれ定義します。これらは、関数の外部 (単一のオブジェクトの外部) から直接アクセスすることはできません。アクセス可能。関数が実行されるとすぐに内部スコープ内のスペースが再利用されるため、クロージャを使用してプライベート プロパティとメソッドをシミュレートできます。この関数 (クロージャ) では、最終的にオブジェクトが返されます。このオブジェクトには、いくつかのパブリック メソッドとプロパティが含まれています。同時に、これらのパブリック メソッドは関数内で定義されているため、それらのプライベート プロパティとただし、外部は返されたパブリック メソッドとプロパティを通じてのみ特定の操作を完了でき、Singleton.privateMethod1 プロパティを直接呼び出すことはできません。これにより、単一のオブジェクトは、外部世界がそのプライベート プロパティやメソッドに直接アクセスできないように隔離できるだけでなく、特定の操作を完了するためにいくつかの共通のプロパティやメソッドを外部世界に提供することもできます。
mySpace.Singleton=(function(){ var uniqueInstance; function constructor(){ var privateAttribute1=false; var privateAttribute1=[1,2,3]; function privateMethod1(){ } function privateMethod2(){ } return { publicAttribute1:true, publicAttribute2:10, publicMethod1:function(){ privateAttribute1=true; privateMethod1(); }, publicMethod2:function(arg){ privateAttribute1=[4,5,6]; privateMethod2(); } } } return { getInstance:function(){ if(!uniqueInstance){ uniqueInstance=constructor(); } return uniqueInstance; } } })();
ここでは、最初に単一のオブジェクトが作成されたかどうかを判断するためのハンドルとして匿名関数内にプライベート変数 uniqueInstance を定義し、次に単一のオブジェクトに対して定義されたすべてのプロパティとメソッドを関数内にコンストラクターに入れます。単一のオブジェクトは関数が呼び出された場合にのみ作成され、それ以外の場合は直接作成されません。次に、getInstance メソッドを含むオブジェクトが返されます。このメソッドを呼び出すときは、最初に単一のオブジェクトが存在するかどうかを確認し、存在しない場合はコンストラクター関数を呼び出します。再び単一のオブジェクトに戻ります。最後に、単一オブジェクトのメソッドを呼び出す場合は、mySpace.Singleton.getInstance().publicMethod1() を使用する必要があります。ここでは、このように呼び出した場合にのみ単一オブジェクトが作成されます。それ以外の場合、単一オブジェクトは作成されません。が自動的に作成され、実際にはオンデマンド読み込みまたは遅延読み込みが実装されます。