13

次のように定義されたJavascriptオブジェクトがある場合:

function MyObj(){};

MyObj.prototype.showAlert = function(){
   alert("This is an alert");
   return;
};

ユーザーは次のように呼び出すことができます。

var a = new MyObj();
a.showAlert();

ここまでは順調で、同じコードで別のインスタンスを実行することもできます。

var b = new MyObj();
b.showAlert();

今知りたいのですが、インスタンス MyObj の数を保持するにはどうすればよいですか? 組み込み関数はありますか?

私が考えている 1 つの方法は、MyObj が初期化されたときにグローバル変数をインクリメントすることです。それがこのカウンターを追跡する唯一の方法ですが、このアイデアよりも優れた方法はありますか?

編集:

ここで提案としてこれを見てください:

ここに画像の説明を入力

どうすれば3ではなく2に戻すことができますか

4

9 に答える 9

20

組み込みのものはありません。ただし、コンストラクター関数に、呼び出された回数のカウントを保持させることができます。残念ながら、JavaScript言語では、オブジェクトがスコープ外になったのか、ガベージコレクションされたのかを判断する方法がないため、カウンターは上がるだけで、下がることはありません。

例えば:

function MyObj() {
  MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
new MyObj();
new MyObj();
MyObj.numInstances; // => 2

もちろん、カウントの改ざんを防ぎたい場合は、クロージャーを介してカウンターを非表示にし、それを読み取るためのアクセサー関数を提供する必要があります。

[編集]

更新された質問によると、JavaScriptはオブジェクトのファイナライザーメソッドを提供しないため、インスタンスが使用されなくなった、または「削除」された時期を追跡する方法はありません(たとえば、変数にnullを割り当てることによって) 。

あなたができる最善のことは、オブジェクトがアクティブでなくなったときに呼び出す「dispose」メソッドを作成することです(たとえば、参照カウントスキームによって)が、これにはプログラマーの協力が必要です-言語は支援を提供しません:

function MyObj() {
  MyObj.numInstances = (MyObj.numInstances || 0) + 1;
}
MyObj.prototype.dispose = function() {
  return MyObj.numInstances -= 1;
};
MyObj.numInstances; // => 0
var a = new MyObj();
MyObj.numInstances; // => 1
var b = new MyObj();
MyObj.numInstances; // => 2
a.dispose(); // 1 OK: lower the count.
a = null;
MyObj.numInstances; // => 1
b = null; // ERR: didn't call "dispose"!
MyObj.numInstances; // => 1
于 2012-09-11T22:39:44.690 に答える
4

MyObjsayというコンストラクターで静的プロパティを作成し、コンストラクターcount内でそれをインクリメントします。

function MyObj() {
    MyObj.count++;
}

MyObj.count = 0;

var a = new MyObj;
var b = new MyObj;

alert(MyObj.count);

これは、たとえばJavaで通常行う方法です(静的プロパティを使用)。

于 2012-09-11T22:45:34.243 に答える
3
var User = (function() {
   var id = 0;
   return function User(name) {
      this.name = name;
      this.id = ++id;
   }
})();

User.prototype.getName = function() { 
    return this.name; 
}

var a = new User('Ignacio');
var b = new User('foo bar');

a
User {name: "Ignacio", id: 1}
b
User {name: "foo bar", id: 2}
于 2015-12-17T16:03:36.430 に答える
1

そのような方法はどうですか?

var Greeter = (function ()
{
    var numInstances;

    function Greeter(message)
    {
        numInstances = (numInstances || 0) + 1;
        this.greeting = message; 
    }

    Greeter.prototype.greet = function ()
    {
        return "Hello, " + this.greeting;
    };

    Greeter.prototype.getCounter = function ()
    {
        return numInstances;
    };

    return Greeter;

})();

var greeter = new Greeter("world");
greeter.greet();
greeter.getCounter();

var newgreeter = new Greeter("new world");
newgreeter.greet();
newgreeter.getCounter();

greeter.getCounter();           
于 2014-12-24T12:56:07.863 に答える
0

最終的に、JS にはプロキシ機能が組み込まれる予定です。これにより、バックグラウンドで発生するあらゆる種類のことへの低レベルのアクセスが可能になり、フロントエンド開発者に公開されることはありません (プロキシを介する場合を除きます。魔法だと考えてください)。 -PHP などの言語のメソッド)。

その時点で、トリガーとしての破壊/ガベージ コレクションのサポートがプラットフォーム間で 100% 保証されている限り、カウンターをデクリメントするデストラクタ メソッドをオブジェクトに記述することは、まったく簡単なことかもしれません。

現在、確実に行う唯一の方法は、作成されたすべてのインスタンスの囲まれたレジストリを作成し、それらを手動で破棄することです (そうしないと、ガベージ コレクションが行われません)。

var Obj = (function () {
    var stack = [],

        removeFromStack = function (obj) {
            stack.forEach(function (o, i, arr) {
                if (obj === o) { arr.splice(i, 1); }
                makeObj.count -= 1;
            });
        };

    function makeObj (name) {
        this.sayName = function () { console.log("My name is " + this.name); }
        this.name = name;
        this.explode = function () { removeFromStack(this); };
        stack.push(this);
        makeObj.count += 1;
    }

    makeObj.checkInstances = function () { return stack.length; };
    makeObj.count = 0;
    return makeObj;

}());


// usage:

var a = new Obj("Dave"),
    b = new Obj("Bob"),
    c = new Obj("Doug");

Obj.count; // 3

// "Dave? Dave's not here, man..."
a.explode();

Obj.count; // 2
a = null;  // not 100% necessary, if you're never going to call 'a', ever again
           // but you MUST call explode if you ever want it to leave the page's memory
           // the horrors of memory-management, all over again

このパターンはあなたがやりたいことをしますか?に限って:

  1. あなたはa別のものに変わりません
  2. explodeそのメソッドを上書きしないでください
  3. あなたは決して台無しにしないでObjください
  4. prototypeメソッドが内部変数にアクセスできるとは思わない

...はい、この方法は、カウンターを適切に機能させるためにうまく機能します。と呼ばれる一般的なメソッドを作成することもできます。このメソッドは、渡したオブジェクトrecycleのメソッドを呼び出しexplodeます (そのコンストラクターまたはファクトリがそのようなことをサポートしている限り)。

function recycle (obj) {
    var key;
    obj.explode();
    for (key in obj) { if (obj.hasOwnProperty(key)) { delete obj[key]; } }
    if (obj.__proto__) { obj.__proto__ = null; }
}

注 - これは実際にオブジェクトを取り除くわけではありません。クロージャーからそれを削除し、かつて持っていたすべてのメソッド/プロパティを削除しただけです。

したがって、これは空の殻であり、再利用しnullたり、部品をリサイクルした後に明示的に設定したり、必要な参照を削除したことを知って収集して忘れたりすることができます.

これは役に立ちましたか?おそらくそうではありません。

これが役に立つと本当に思うのは、キャラクターが一度に 3 発しか発射できないゲームで、画面上の最初の弾丸が誰かに当たるか消えるまで 4 発目を撃つことができない場合だけです。エッジ(これは、たとえば、コントラがその日にどのように機能したかです)。

また、「消えた」弾丸をスタックから移動し、弾道をリセットし、適切なフラグをリセットし、スタックに戻すことで、その弾丸を任意のプレイヤー/敵に再利用することもできます。

しかし、繰り返しになりますが、プロキシによって「魔法の」コンストラクタ/デストラクタ メソッドを定義できるようになるまでは、これらのメソッドは低レベルで受け入れられます。これは、独自のオブジェクトすべての作成と破棄を細かく管理する場合にのみ役立ちます (実際にはそうではありません)。良い考えです)。

于 2012-09-11T23:40:43.640 に答える
0
        class Patient{
        
        constructor(name,age,id){        
            Object.assign(this,{name, age, id});    
            
        }
        static patientList = []; // declare a static variable
        static addPatient(obj){       
            this.patientList.push(...obj); // push to array
            return this.patientList.length; // find the array length to get the number of objects
        }
        
    }
    
    let p1 = new Patient('shreyas',20, 1);
    let p2 = new Patient('jack',25, 2);
    let p3 = new Patient('smith',22, 3);
    let patientCount = Patient.addPatient([p1,p2,p3]); // call static method to update the count value with the newly created object
   console.log(Patient.patientList);
    console.log(patientCount);
于 2021-04-08T12:08:29.573 に答える