1

さて、私は他の多くのOOP言語のように、プレーンな古いJavascriptにある種の拡張継承を持たせる方法を見つけようとしてきました。しかし、クラスがプロトタイプを使用して親クラスを拡張すると、そのオブジェクトの各子が親の独自の新しいインスタンスを持つのではなく、変数を共有するという特定の問題が発生しました。例えば:

TestB.prototype = new TestA();
function TestB(){ }

function TestA(){
    var num = 0;    
    this.count = function(){
        num ++;
        console.log(num);
    }
}

var test = new TestB();
test.count();
var test2 = new TestB();
test2.count();

したがって、コードを実行すると、コンソールは次のようになります。

1
2

親クラスから継承される「num」変数がそれぞれのインスタンスに固有であるため、出力は次のようになります。

1
1

これは、プロトタイプが呼び出されたときに、TestBのコンストラクターが呼び出されるたびに1つではなく、TestAの新しいインスタンスが1つだけ作成されるためだと思います。問題は、それを機能させる別の方法を見つけることができなかったことです。

助けてくれてありがとう(そしてこれは実際にはもっと具体的な用途のためですが、問題をきれいに説明するために非常に単純なテストケースを作成したかっただけです。jQueryやprototype.jsなどの外部ライブラリを使用する自由がありませんこの問題を解決するために)

4

3 に答える 3

3

コンストラクターではなく、プロトタイプでメソッドを定義することになっています。これにより、メモリが節約され、パフォーマンスが向上するだけでなく、クラスをクリーンに拡張できます。

function TestA() {
    this.num = 0;
}

TestA.prototype = {

    count: function() {
        console.log( this.num++ );
    },

    constructor: TestA
};

function TestB(){
    TestA.apply( this, arguments ); //Run parent constructor when instantiating a child
}

TestB.prototype = Object.create( TestA.prototype ); //Don't invoke the constructor when merely establishing inheritance


var test = new TestB();
test.count(); //0
var test2 = new TestB();
test2.count(); //0
于 2012-05-29T17:15:58.870 に答える
0

私の知る限り、プロトタイプはプロパティを読み取るときにのみ機能します。プロトタイプではなくインスタンスを介してプロパティを編集すると、インスタンスは同じ名前と編集された値の独自のプロパティを作成します。プロトタイプの値は同じままです。

あなたの例では、外部からは見えないプライベート変数を持ち越しました。したがって、「編集」することはできず、継承するクラスのすべてのインスタンスを通じてその値を保持します。

このサンプルでは、​​これをnum公開して、インスタンスレベルで編集可能かつ「パッチ可能」にします。

var test, test2;

function TestA() {
    this.num = 0;               //public num
    this.count = function() {
        this.num++;
        console.log(this.num);
    }
}

function TestB() {}            //instances of TestB don't have properties
TestB.prototype = new TestA();

test = new TestB();
test2 = new TestB();

//monitor the instances
console.log(test);
console.log(test2);

test.count();   //these create a num property at the instance level
test2.count();  //but the prototype num remains 0  
test2.count();
test2.count();  ​//test will have 1 and test2 will have 3

カウント操作の前:

Object -> TypeA -> TypeB -> test
           '-> num = 0       '->num = 0 (from TypeA)
           '-> count()       '->count() (from TypeA)

Object -> TypeA -> TypeB -> test2
           '-> num = 0       '->num = 0 (from TypeA)
           '-> count()       '->count() (from TypeA)

カウント操作の後、プロトタイプnumは0のままで、インスタンスは次のようになりますnum

Object -> TypeA -> TypeB -> test
           '-> num = 0       '->num = 1 (on the instance)
           '-> count()       '->count() (from TypeA)

Object -> TypeA -> TypeB -> test2
           '-> num = 0       '->num = 3 (on the instance)
           '-> count()       '->count() (from TypeA)
于 2012-05-29T17:19:37.853 に答える
0

インスタンスの継承されたプロパティに書き込むとすぐに、そのインスタンスのプロパティの新しいコピーが作成されます。

たとえば、次のようなものがあるとします。

var objB1 = new TypeB();
var objB2 = new TypeB();

ここで、TypeBvalはTypeAからプロパティを継承します。

console.log(objB1.val);  // reads the inherited value of property val
console.log(objB2.val);  // also reads the inherited value of property val

しかし、そのプロパティを記述した瞬間、次のようになります。

objB1.val = 35; // objB1 now gets a new copy of the val property.

また

objB1.val++; // objB1 now gets a new copy of the val property.

上記の両方の場合で、objB1.valが書き込まれると、継承されたプロパティを参照しなくなりますが、代わりにプロパティの新しいコピーvalが作成されます(例:objB1)。

カウントを保存したい場合、1つの方法はそれを共有することです。便宜上、親クラスのコンストラクター関数のプロパティにすることができます。したがって、カウント関数は次のようになります。

function TestA(){
    this.count = function(){
        TestA.num++;
        console.log(TestA.num);
    }
};

TestA.num = 0;

于 2012-05-29T17:57:40.327 に答える