Javascriptはコンストラクション関数を単純なファクトリに拡張

5388 ワード

一般的にJavascriptでオブジェクトを作成する際にはキーワードnew(コンストラクション関数別に呼び出す)を使用する必要がありますが、開発者はnewキーワードが明示的に使用されているかどうかにかかわらず、コンストラクション関数が正常に呼び出されることを望んでいます.すなわち、コンストラクション関数は単純な工場の機能も備えています.Javascriptの1つの特性はこのような「単純なファクトリ式の構造関数」を実行可能にした:構造関数にオブジェクトが返された場合、newキーワードを使用するかどうかにかかわらず、最終的に返される値は関数returnの値である.
この点の特性に基づいて、本文は4種類の実現方式を紹介して、レンガを投げて玉を引いて、レンガを撮ることを歓迎します~
1.コンストラクション関数でオブジェクトの字面量を返す
 1 function Person(name) {
 2     return {
 3         name: name,
 4         getName: function () { 
 5             return this.name;
 6         }
 7     };
 8 }
 9 console.log(new Person('Ralph').getName()); //Ralph
10 console.log(Person('Ralph').getName()); //Ralph

欠点:prototypeプロパティの制御が不便で、効率的な拡張オブジェクトメソッドに不利で、instanceofオペレータが失効し、constructorプロパティが失われる
 
2.コンストラクション関数で内部関数を使用してオブジェクトを構築する
 1 function Person(name) {
 2     // lazy loading, Person                _Person
 3     if (!Person.inited) {
 4         Person._Person = function (name) {
 5             this.name = name; 
 6         };
 7         //     prototype      
 8         Person._Person.prototype = {
 9             //     constructor  
10             constructor: Person,
11             getName: function () {
12                 return this.name;
13             }
14         };
15         //       instanceof    
16         Person.prototype = Person._Person.prototype;
17         //        
18         Person.inited = true;
19     }
20     return new Person._Person(name);
21 }
22 console.log(new Person('Ralph').getName()); //Ralph
23 console.log(Person('Ralph').getName()); //Ralph

欠点:符号化は比較的複雑で、必要とする.Personは補助的な内部構造関数としてprototypeやconstructorなどの属性を手動で変更する必要がある
 
3.instanceofオペレータの利用
 1 function Person(name) {
 2     //      new,this      Person  
 3     //       Person    new,   this  window   
 4     if (!(this instanceof Person)) {
 5         return new Person(name);
 6     }
 7     this.name = name;
 8 }
 9 Person.prototype.getName = function () {
10     return this.name;
11 };
12 console.log(new Person('Ralph').getName()); //Ralph
13 console.log(Person('Ralph').getName()); //Ralph

欠点:this instanceof Personを判断する際にコンストラクション関数名Personを指定する必要があり、抽象度が高くなく、コンストラクション関数名を変更する際に手動で文を変更する必要がある
 
4.callee属性とconstructor属性を利用する
 1 function Person(name) {
 2     // arguments.callee  Person  
 3     // this.constructor     new      Person  
 4     if (arguments.callee !== this.constructor) {
 5         return new arguments.callee(name);
 6     }
 7     this.name = name;
 8 }
 9 Person.prototype.getName = function () {
10     return this.name;
11 };
12 console.log(new Person('Ralph').getName()); //Ralph
13 console.log(Person('Ralph').getName()); //Ralph

欠点:strictモードではcalleeプロパティを使用できません
(全文完了)