JavaScript には、カスタム プロパティとメソッドを使用してオブジェクトを作成するためのモードが多数あり、以下で 1 つずつ紹介します。
1. パターンを直接作成します。これは最も単純かつ単純なパターンで、最初に参照型のオブジェクトを作成し、次にカスタム プロパティとメソッドをそれに追加します。サンプルコードは次のとおりです:
1 var person = new Object();
2 person.name = "Sam";
3 person.age = 16;
4 person.speak = function(){
5alert (this. name + "is " + this.age + "years old");
6 }
7 person.speak();
上記で Object 型のオブジェクトが作成され、次に名前と年齢が作成されていることがわかります。プロパティとspeakメソッドが追加されます。パターンを直接作成するのは簡単ですが、その欠点は明らかです。同じオブジェクトを多数作成する必要がある場合、毎回コードを繰り返し書かなければなりません。この問題を解決するには、オブジェクトの作成プロセスをカプセル化することができるため、次のファクトリ パターンを用意します。
2. 工場出荷時モード。ファクトリ パターンは、プログラミングでよく使用されるデザイン パターンで、主にオブジェクトを作成するプロセスをカプセル化します。 サンプル コードは次のとおりです。 3 person.name = 名前;
5 person.speak = function(){
6 alter(this.name + "は " + this.age + "歳");
7 }
8 return person;
9 }
10 var person1 = createperson("Sam", 16);
11 var person2 = createperson("Jack", 18);
ファクトリパターンを使用した後、同じタイプのオブジェクトを作成しますシンプルになりました。しかし、ファクトリ パターンではオブジェクトの識別の問題は解決されません。つまり、作成されたオブジェクトの特定のタイプを決定することができません。オブジェクト指向プログラミングの経験がある開発者は、オブジェクトの作成はクラスに基づいて行う必要があることを知っています。特定のカスタム クラスを取得したら、そのクラスのオブジェクトを作成できます。幸いなことに、JavaScript では、コンストラクター パターンを通じてクラスをシミュレートできます。
3. コンストラクターパターン。コンストラクターと通常の関数の間に違いはありません。 new 演算子が使用されている限り、任意の通常の関数をコンストラクターとして使用できます。また、任意のコンストラクターを通常の関数として呼び出すこともできます。ただし、JavaScript では、コンストラクターとして使用される関数名の最初の文字を大文字にする必要があるという規則があります。サンプルコードは以下の通りです:
2 this.name = name;
3 this.age = age;
5alert(this .name + "は " + this.age + "歳");
6 }
7 }
8 var person1 = 新しい人("サム", 16);
9 var person2 = 新しい人("ジャック", 18);
コンストラクター内でこれを使用してプロパティとメソッドを追加していることがわかります。 Person オブジェクトを作成するとき、これは作成されたオブジェクトを指します。これで、オブジェクト person1 と person2 の特定のタイプを識別できるようになりました。 alert(person1 instanceOf Person) を使用すると、出力値が true であることがわかります。ただし、コンストラクター パターンには独自の欠点もあります。つまり、コンストラクター内で宣言されたメソッドは、新しいオブジェクトが作成されるたびに再作成されます (JavaScript では、関数もオブジェクトです)。つまり、コンストラクター内のメソッドは、クラスではなくオブジェクトにバインドされます。以下のコードの出力で推論を検証できます。
1 alter(person1.speak == person2.speak); // false
この欠点を解決する比較的簡単な方法は、関数宣言をコンストラクターの外に置くことです。つまり、
2 this.name = name;
3 this.age = age;
5 }
6 function speech(){
7 alter(this.name + "は " + this.年齢 + "歳");
8 }
9 var person1 = 新しい人("サム", 16);
10 var person2 = 新しい人("ジャック", 18);
11 アラート(人1.speak == person2.speak); // 本当
問題は解決されましたが、この方法は新たな問題をもたらします。まず、関数 speech はグローバル スコープで宣言されていますが、グローバル スコープに配置すると誤用の危険性があります。次に、カスタム タイプに多くのメソッドがある場合、次のようにする必要があります。多くのグローバル関数を宣言すると、グローバル スコープの汚染につながるだけでなく、コードのカプセル化にも役立ちません。それでは、グローバル スコープを汚さずにクラスにバインドされたカスタム型メソッドを作成する方法はあるのでしょうか?答えは、プロトタイプ パターンを使用することです。
4. プロトタイプモード。新しい関数を宣言すると、その関数 (JavaScript では関数もオブジェクトです) はプロトタイプ属性を持ちます。プロトタイプは、この関数によって作成されたすべてのオブジェクトが所有するパブリック プロパティとメソッドを表すオブジェクトです。サンプル コードは次のとおりです。
1 関数 person(){}
2 person.prototype.name="Sam";
3 person.prototype.age=16;
4 person.prototype.speak = function() {
5 アラート(this.name + "は " + this.age + "歳");
6 }
7 var person1 = 新しい Person();
8 person1.speak();
9 var person2 = 新しいperson() ;
10 alter(person1.speak == person2.speak); // true
コンストラクター内でspeakメソッドが宣言されていませんが、作成したオブジェクトperson1は依然としてspeakメソッドを呼び出すことができることがわかります。これは、JavaScript には最初にインスタンスの属性とメソッドを検索し、見つからない場合は戻り、プロトタイプで再度検索するという検索ルールがあるためです。プロトタイプ パターンでは、メソッドがクラスに関連付けられ、グローバル スコープを汚染しませんが、独自の欠点もあります。まず、すべての属性もクラスに関連付けられます。つまり、すべてのオブジェクトが 1 つの属性を共有することになり、これは明らかに不合理です。 . ; 次に、初期化データをコンストラクターに渡す方法がありません。解決策は簡単で、コンストラクター パターンとプロトタイプ パターンを組み合わせて使用するだけです。
5. 組み合わせモード。サンプルコードは次のとおりです。
1 function person(name, age){
2 this.name = name;
3 this.age = age;
4 }
5 person.prototype.speak = function(){
6 アラート (this.name + "は " + this.age + "years old");
7 }
8 var person1 = 新しい人();
9 person1.speak();
10 var person2 = 新しい人();
11 alter(person1.speak == person2.speak); // true
組み合わせモードがすべてのニーズを満たすことは難しくありません。また、現在広く使用されているモードでもあります。オブジェクト指向プログラミングの経験のある開発者にとっては、プロトタイプ宣言をコンストラクターの外に置くのは少し面倒に感じるかもしれませんが、コンストラクターの中に置くことはできますか?答えは「はい」です。動的結合モードを使用してください。
6. ダイナミックコンビネーションモード。原則として、まずプロトタイプ内の特定の属性またはメソッドが宣言されているかどうかを判断し、宣言されていない場合はプロトタイプ全体を宣言し、何も実行しません。サンプルコードは以下の通りです:
1 function Person(name, age){
2 this.name = name;
3 this.age = age;
4 if (person.prototype.speak == "unknown") {
5 パーソン.prototype.speak = function(){
6 アラート(この名前 + "は " + この.年齢 + "歳");
7 }
8 }
9 }