0

JavaScriptでクラスを定義するために使用できる手法と、それらのトレードオフは何ですか? スタックオーバーフローで、クラスを定義できることを理解しています

方法 1:

function Person(name, gender){
   this.name = name;
   this.gender = gender;
}

インスタンス化されるたびにメンバー関数が再作成されないように、プロトタイプに関数を追加します。お気に入り

Person.prototype.speak = function(){
   alert("my name is" + this.name);
}

を介してそのインスタンスを作成します

var person = new Person("Bob", "M"); 

のような新しいキーワードなしで同じオブジェクトの作成が可能だと思います

方法 2:

var Person = function (name, gender) {

    return {name:name, gender:gender}; 

}

person  = Person("Bob", "M");

2番目の方法は、最初の方法とまったく同じことをしていますか? また、もしそうなら、2番目のアプローチで(方法1の話でわかるように)プロトタイプを介して関数の追加をどのようにモックアップしますか?

4

4 に答える 4

3

Sean Vieira が説明したように、最初の方法は 2 番目の方法と同じではありません。最初のメソッドでは、インスタンスは から継承しPerson.prototypeます。2 番目の方法では、インスタンスは から直接継承しますObject.prototype

方法 1:

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
| Person.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+

方法 2:

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+

興味深いことに、上の図は、オブジェクトがコンストラクターからではなく、JavaScriptの他のオブジェクトから継承することを示しています。したがって、インスタンスを作成すると、それ自体ではなく からnew Person継承されます。Person.prototypePerson

この関連情報はどうですか?手始めに、オブジェクトのインスタンスを作成するためにコンストラクターを作成する必要がないことを示しています。代わりに、次のようにプロトタイプ オブジェクトを直接作成します。

var person = {
    create: function (name, gender) {
        var person = Object.create(this);
        person.gender = gender;
        person.name = name;
        return person;
    },
    speak: function () {
        alert("My name is " + this.name + ".");
    }
};

上記の例personでは、 と同等Person.prototypeです。person次のように のインスタンスを作成できます。

var bob = person.create("Bob", "M");

のプロトタイプ チェーンは次のbobようになります。

        null
         ^
         |
         | __proto__
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|      person      |
+------------------+
         ^
         |
         | __proto__
         |
+------------------+
|       bob        |
+------------------+

では、なぜ代わりにこのようなオブジェクトを作成する必要があるのでしょうか?

  1. よりきれいに見えます。すべてが単一のオブジェクト リテラルにカプセル化されます。
  2. オブジェクトがオブジェクトから継承されることを理解するのは簡単です。コンストラクターは必要ありません。
  3. newインスタンスの作成に使用する必要はありません。これにより、多く問題が解決されます。

このパターンの詳細については、「Why Prototypal Inheritance Matters」に関する私のブログ投稿を参照してください。

于 2013-07-03T02:42:08.460 に答える
0

たぶん、この答えは、コンストラクター関数、継承、プライベート変数、およびメソッドのオーバーライドについてもう少し説明できます:プロトタイプの継承 - 書き上げ

他の回答はすでにあなたの質問に対処しています。オブジェクト リテラルとしてオブジェクト{prop:val,method:function(){}}を作成し、コンストラクタ関数を使用してオブジェクトを作成しますvar MyObject=function(){this.prop=val};MyObject.prototype.method=function(){}

于 2013-07-03T01:31:49.153 に答える
0

あなたの例は、プロパティへのアクセスに関して同じことを達成していますが、最初のメソッドには基本的なObjectプロトタイプがあるため、それらは同一ではありません。2 番目の質問に対する答えは次のとおりです。

function Person( name, gender ){
   return {
     name: name,
     gender: gender,
     speak: function(){
        alert("my name is" + this.name);
     }
   };
}

ここにはプロトタイプはありません。関数はオブジェクト リテラルに焼き付けられます。プロトタイプの代わりにリテラルを使用する唯一の価値は、クロージャーを作成して、プライベート変数を持つことができるようにすることです。

function Person( name, gender ){
   return {
     speak: function(){
        alert("my name is" + name);
     }
   };
}
于 2013-07-02T18:27:26.627 に答える