在Javascript中获取类的所有实例

13

我认为会有已经回答这个问题的方法,但是我似乎找不到一个.. 如何在Javascript中运行特定类的所有实例的类方法?

在我不知道实例名称的情况下进行操作。 我想我可以在我的类内部使用某种静态变量来存储所有实例,但是在JS中似乎不存在这种方式。

那么如何在我的类的所有现有实例上调用我的方法? 注意:仅作澄清:我所说的“类”并非指CSS类,而是指对象。

编辑:通过Javascript中的类,我是指在函数上创建新对象:

function something()
{
}

var instance = new something();

4
你正在要求创建一个内存泄漏。 - SLaks
document.getElementsByClassName()?jQuery的class选择器?我有什么遗漏吗? - JJJ
1
哦,我明白了。(JavaScript 中没有类,所以这个术语把我搞混了。) - JJJ
可能是循环遍历JavaScript对象的所有实例的重复问题。 - JJJ
2
通常只需要知道所说对象的一个(提示!)集合。利用这个想法将对象分组成适当的(分层)集合,并围绕此设计API。例如,Map可能有许多Point,但通常不关心创建的每个Point;相反,只有属于特定Map中适当的点集合的Points才是感兴趣的。 - user2864740
显示剩余3条评论
6个回答

19

您可以创建一个静态数组并将其存储在构造函数中:

MyClass.allInstances = [];
MyClass.allInstances.push(this);

但是,您需要一种方法来确定何时从此数组中移除实例,否则将会泄漏内存。


好的,现在我明白你为什么谈论内存泄漏了。那我会实现某种形式的析构函数。 - Vincent Duprez
你不能把'MyClass.allInstances = []'放在构造函数中,这会每次创建一个空数组 :( - Damjan Pavlica
@DamjanPavlica:当然,它们需要放在不同的地方。 - SLaks
@DamianPavlica 这个 if(!MyClass.allInstances) { MyClass.allInstances = []; } 怎么样? - 9me

14
在Chrome 62+中,你可以使用控制台API的queryObjects函数 - 它不会在原生JavaScript代码中工作,但在控制台中运行,因此非常适用于调试。
class TestClass {};
const x = new TestClass();
const y = new TestClass();
const z = new TestClass();
queryObjects(TestClass)

9
您需要提供自定义实现。
我会这样做:
function Class() {
    Class.instances.push(this);
};
Class.prototype.destroy = function () {
    var i = 0;
    while (Class.instances[i] !== this) { i++; }
    Class.instances.splice(i, 1);
};
Class.instances = [];

var c = new Class();
Class.instances.length; // 1
c.destroy();
Class.instances.length; // 0

或者像这样:
function Class() {};
Class.instances = [];
Class.create = function () {
    var inst = new this();
    this.instances.push(inst);
    return inst;
};
Class.destroy = function (inst) {
    var i = 0;
    while (Class.instances[i] !== inst) { i++; }
    Class.instances.splice(i, 1);
};

var c = Class.create();
Class.instances.length; // 1
Class.destroy(c);
Class.instances.length; // 0

然后你可以这样循环遍历所有实例:
Class.each = function (fn) {
    var i = 0, 
        l = this.instances.length;
    for (; i < l; i++) {
        if (fn(this.instances[i], i) === false) { break; }
    }
};

Class.each(function (instance, i) {
    // do something with this instance
    // return false to break the loop
});

8

非常抱歉回复晚了,但我发现自己试图实现这个功能,我认为这可能是一个更简单的答案。

比如说你想获取所有MyClass类的实例,只获取在顶层窗口创建的实例(不包括在闭包内创建的实例):

for (var member in window)
{
    if (window[member] instanceof MyClass)
        console.info(member + " is instance of MyClass");
}

4

现在类中可以使用关键字“static”了(但要检查支持情况),...

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/static

class Point{
    constructor(x, y){
        this.x = x;
        this.y = y;
        Point.all.push(this);
    }
    destroy(){
        let i = Point.all.indexOf(this);
        Point.all.splice(i, 1);
    }
    static all = [];
}

var p1 = new Point(1, 2);
var p2 = new Point(54, 33);
var p3 = new Point(297, 994);

console.log(JSON.stringify(Point.all)); //[{"x":1,"y":2},{"x":54,"y":33},{"x":297,"y":994}]

p2.destroy();
console.log(JSON.stringify(Point.all)); //[{"x":1,"y":2},{"x":297,"y":994}]


2

您需要自己存储实例列表:

function someClass(param) {

  // add to all
  if (this.constructor.all === undefined) {
    this.constructor.all = [this];
  } else {
    this.constructor.all.push(this);
  }

  // set param
  this.logParam = function() { console.log(param); };
}

var instance1 = new someClass(1);
var instance2 = new someClass(2);

for (var i = 0; i < someClass.all.length; i++) {
  someClass.all[i].logParam();
}

如果内存泄漏是一个问题,那么你可以创建一个方法,在使用完实例后将其删除:

function someClass(param) {

  ...

  this.destroy = function() {
    var all = this.constructor.all;
    if (all.indexOf(this) !== -1) {
      all.splice(all.indexOf(this), 1);
    }
    delete this;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接