4

私がこのコードを持っているとしましょう:

function ParentClass()
{
    var anArray = [ ];

    this.addToArray = function(what)
    {
        anArray.push(what);

        console.log(anArray);
    };
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass()
{
    this.addToArray('FirstSubClass');
}

SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;

function SecondSubClass()
{
    this.addToArray('SecondSubClass');
}

実行するnew FirstSubClass()と、コンソールに単一の値の配列が表示されます。また、を実行するnew SecondSubClass()と、単一の値の配列が表示されます。

しかし、それらを再度実行すると(つまりnew FirstSubClass(); new SecondSubClass();)、新しい配列が作成されるのではなく、追加された配列が表示されるのはなぜですか?

ここでの理論的根拠は、クラスの新しいインスタンスを作成しているということです。それで、なぜそれらは同じプライベートプロパティを共有しているのでしょうか。

これを回避するにはどうすればよいnew FirstSubClass()でしょうか。たとえば、クラスの新しいインスタンスを何度作成しても、単一の値の配列が表示されます。

4

5 に答える 5

3

サブクラスごとにnew ParentClass() 1 回しか呼び出していないことに注意してください。つまり、プライベート配列変数は、これらのサブクラスのプロトタイプ オブジェクトの一部です。プロトタイプ オブジェクトは 1 つしかないため、配列は (サブクラスごとに) 1 つだけです。

を呼び出すたびにnew FirstSubClass()、同じプロトタイプ オブジェクトを共有する新しいインスタンスが生成されます。したがって、の呼び出しはaddToArray()、プロトタイプ オブジェクトが作成されたときに作成された同じ配列に要素を追加します。

編集— イ​​ンスタンスごとの配列が必要な場合は、次のようにする必要があります。

function ParentClass() {
  this.addToArray = function(value) { this.instanceArray.push(value); };
};

function FirstSubClass() {
  this.instanceArray = [];

  this.addToArray("First");
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
于 2013-01-06T16:15:20.380 に答える
2

まず、JS でのサブクラス化は通常、悪い考えです。なぜなら、すべてのインスタンスがプロパティとメソッドの独自のコピーを持っている拡張機能を取得していると人々が考えているからです...

...本当に、彼らはpublic static親のものにアクセスしています。

さらに良いことに、そのようなpublic staticものはカプセル化された変数にアクセスできないため、(パブリック インターフェイスを使用して) プライベート関数を使用してパブリックな静的データにデータを渡したり、そこから戻り値を収集したりしない限り、実際にはプライベート データを操作することはありません。

var Parent = function () {
    this.static_prop = 0;
    this.static_method = function (num) { this.static_prop += 1; return num + this.static_prop; };
};

var Child = function (num) {
    this.public_func = function () { num = this.static_method(num); };
};

Child.prototype = new Parent();

var child = new Child(13);
child.public_func();

this.static_methodへのアクセスが0になるため、呼び出すだけでは役に立ちませんnum。つまり、継承したものをラップして、プライベートデータを入力として使用するためのアクセスを許可することになります。つまり、ほとんどの書き込みを行うことになります。あなたの期待.prototypeは逆 だったので、継承に関係なく、とにかくやっているでしょう。

代わりに、依存性注入をお勧めしますか?
コンポーネントベースのプログラム?

var Iterator = function () {
    var count = 0,
        min = 0,
        max = 0,

        reset = function () { count = min; },
        next = function () { count = count >= max ? min : count; return count += 1; },
        set_min = function (val) { min = val; },
        set_max = function (val) { max = val; },
        public_interface = { reset : reset, count : count, set_min : set_min, set_max : set_max };

    return public_interface;
},


Thing = function (iter) {
    var arr = [],

        currentObj = null,
        nextObj = function () {
            currentObj = arr[iter.next()];
        },
        add = function (obj) {
            arr.push(obj); iter.set_max(arr.length);
        },
        public_interface = { next : nextObj, add : add };

    return public_interface;
};


var thing = Thing(Iterator());
thing.add({});
thing.next();

これは複雑な例ですが、すべてのインスタンスには、ジョブを実行するために必要なものが正確に与えられます (コンストラクターが必要とするため、または、パブリック メソッドを介して、またはパブリック プロパティとして、後で依存関係を追加できます)。 .

各モジュールのインターフェイスは、プライベート データを取得するために予期しない静的ヘルパーをラップする必要がないため、必要に応じてシンプルかつクリーンにすることもできます...

これで、何がプライベートで、何がパブリックに拡張されているかがわかり、それらを配置したい場所にクリーンなインとアウトがあります。

于 2013-01-06T16:55:41.337 に答える
1

サブクラスごとに 1 回だけ ParentClass の新しいインスタンスを作成し、それをプロトタイプに適用します。各インスタンスにプライベート配列の独自のコピーと関数「addToArray」の独自のコピーを持たせたい場合は、他のオブジェクト コンストラクター内で ParentClass コンストラクター関数を呼び出す必要があります。

function ParentClass(){
    var anArray = [ ];

    this.addToArray = function(what){
        anArray.push(what);
        console.log(anArray);
    };
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass(){
    //call the parents constructor where "this" points to your FirstSubClass instance
    ParentClass.call( this );
    this.addToArray('FirstSubClass');
}

SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;

function SecondSubClass(){
    ParentClass.call( this );
    this.addToArray('SecondSubClass');
}
于 2013-01-07T15:54:40.973 に答える
0

これを試して:

http://jsfiddle.net/3z5AX/2/

function ParentClass()
{
    var anArray = [ ];

    this.addToArray = function(what)
    {
        anArray.push(what);

       document.getElementById("i").value = anArray;
    };
}

//FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass()
{  
  this.parent = new ParentClass()
  this.parent.addToArray('FirstSubClass');
}


var q = new FirstSubClass();
var r = new FirstSubClass();
于 2013-01-06T16:29:21.883 に答える
0

すべてのサブクラスは同じ親クラスを共有するため、同じプライベート anArray

解決策は、Mixin パターンを使用することです。

// I have the habbit of starting a mixin with $
var $AddToArray = function(obj) {
    var array = [];

    obj.addToArray = function(what) {
        array.push(what);
        console.log(array);
    };
}

var FirstClass = function() {
    $AddToArray(this);
}

var SecondClass = function() {
    $AddToArray(this);
}
于 2013-01-06T16:32:37.113 に答える