javascript - 如何获取 javascript 对象引用或引用计数?

标签 javascript garbage-collection reference

如何获取对象的引用计数

  • 是否可以确定一个 javascript 对象是否对其有多个引用
  • 或者它是否有引用除了我正在访问它的引用
  • 或者甚至只是获取引用计数本身?
  • 我能否从 javascript 本身找到此信息,或者我是否需要跟踪我自己的引用计数器。

显然,对于我的代码访问该对象,必须至少有一个对它的引用。但我想知道的是是否有任何其他对它的引用,或者我的代码是否是唯一访问它的地方。如果没有其他对象引用它,我希望能够删除该对象。

如果您知道答案,则无需阅读此问题的其余部分。下面只是一个示例,目的是让事情更清楚。


用例

在我的应用程序中,我有一个名为 contactsRepository 对象实例,其中包含我的ALL 联系人数组。还有多个 Collection 对象实例,例如 friends 集合和一个 coworkers 集合。每个集合都包含一个数组,其中包含来自 contacts Repository 的不同项目集。

示例代码

为了使这个概念更具体,请考虑以下代码。 Repository 对象的每个实例都包含特定类型的所有项的列表。您可能有一个联系人 存储库和一个单独的事件 存储库。为简单起见,您只需获取、添加和删除项,并通过构造函数添加许多项。

var Repository = function(items) {
  this.items = items || [];
}
Repository.prototype.get = function(id) {
  for (var i=0,len=this.items.length; i<len; i++) {
    if (items[i].id === id) {
      return this.items[i];
    }
  }
}
Repository.prototype.add = function(item) {
  if (toString.call(item) === "[object Array]") {
    this.items.concat(item);
  }
  else {
    this.items.push(item);
  }
}
Repository.prototype.remove = function(id) {
  for (var i=0,len=this.items.length; i<len; i++) {
    if (items[i].id === id) {
      this.removeIndex(i);
    }
  }
}
Repository.prototype.removeIndex = function(index) {
  if (items[index]) {
    if (/* items[i] has more than 1 reference to it */) {
      // Only remove item from repository if nothing else references it
      this.items.splice(index,1);
      return;
    }
  }
}  

注意 remove 中带有注释的行。如果没有其他对象引用该项目,我只想从我的对象主存储库中删除该项目。这是集合:

var Collection = function(repo,items) {
  this.repo = repo;
  this.items = items || [];
}
Collection.prototype.remove = function(id) {
  for (var i=0,len=this.items.length; i<len; i++) {
    if (items[i].id === id) {
      // Remove object from this collection
      this.items.splice(i,1);
      // Tell repo to remove it (only if no other references to it)
      repo.removeIndxe(i);
      return;
    }
  }
}

然后此代码使用RepositoryCollection:

var contactRepo = new Repository([
    {id: 1, name: "Joe"},
    {id: 2, name: "Jane"},
    {id: 3, name: "Tom"},
    {id: 4, name: "Jack"},
    {id: 5, name: "Sue"}
  ]);

var friends = new Collection(
  contactRepo,
  [
    contactRepo.get(2),
    contactRepo.get(4)
  ]
);

var coworkers = new Collection(
  contactRepo,
  [
    contactRepo.get(1),
    contactRepo.get(2),
    contactRepo.get(5)
  ]
);

contactRepo.items; // contains item ids 1, 2, 3, 4, 5 
friends.items;  // contains item ids 2, 4
coworkers.items;  // contains item ids 1, 2, 5

coworkers.remove(2);

contactRepo.items; // contains item ids 1, 2, 3, 4, 5 
friends.items;  // contains item ids 2, 4
coworkers.items;  // contains item ids 1, 5

friends.remove(4);

contactRepo.items; // contains item ids 1, 2, 3, 5 
friends.items;  // contains item ids 2
coworkers.items;  // contains item ids 1, 5

请注意 coworkers.remove(2) 没有从 contactRepo 中删除 id 2?这是因为它仍然被 friends.items 引用。但是,friends.remove(4) 导致 id 4 从 contactRepo 中删除,因为没有其他集合引用它。

总结

以上是我想做的。我确信有一些方法可以通过跟踪我自己的引用计数器等来做到这一点。但是,如果有一种方法可以使用 javascript 的内置引用管理来做到这一点,我想听听如何使用它。

最佳答案

不,不,不,不;是的,如果你真的需要计算引用,你将不得不手动完成。 JS没有this、GC、weak references接口(interface)。

虽然您可以实现一个手动的引用计数对象列表,但值得怀疑的是所有额外的开销(在性能方面,但更重要的是代码复杂性)是否值得。

在您的示例代码中,忘记 Repository 似乎更简单,为您的列表使用普通的 Array,并让标准垃圾收集负责丢弃未使用的人。如果您需要获取所有在用人员的列表,您只需concat friendscoworkers 列表(并对它们进行排序/唯一化)如果你需要的话)。

关于javascript - 如何获取 javascript 对象引用或引用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2937120/

相关文章:

python - 如何制作即使在 Python 中引发异常的情况下也能解锁的目录锁

java - 将一个类实例传递给另一个类

javascript - 在Firebase中使用push()时如何存储在我的数据库中

javascript - 当用户未登录到应用程序时,使用 React 路由重定向的正确方法是什么?

java - 当不再使用时将 null 分配给 ref 有什么好处吗?

C++ 在 std::map 中存储对值的引用

c++ - (悬空?)从函数返回的引用不是 "work"

javascript - contenteditable ="true": creating a syntax highlighted input form

javascript - 使用来自 json 响应的动态布局 : angularJS

memory - 在 Go 中使用指针作为映射键是否安全?