如何获取 javascript 对象引用或引用计数? [英] How to get javascript object references or reference count?

查看:30
本文介绍了如何获取 javascript 对象引用或引用计数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

Obviously, there must be at least one reference to it for my code access the object. But what I want to know is if there are any other references to it, or if my code is the only place it is accessed. I'd like to be able to delete the object if nothing else is referencing it.

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

If you know the answer, there is no need to read the rest of this question. Below is just an example to make things more clear.

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

In my application, I have a Repository object instance called contacts that contains an array of ALL my contacts. There are also multiple Collection object instances, such as friends collection and a coworkers collection. Each collection contains an array with a different set of items from the contacts Repository.

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

To make this concept more concrete, consider the code below. Each instance of the Repository object contains a list of all items of a particular type. You might have a repository of Contacts and a separate repository of Events. To keep it simple, you can just get, add, and remove items, and add many via the constructor.

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 中带有注释的行.如果没有其他对象引用该项目,我只想从我的对象主存储库中删除该项目.这是集合:

Note the line in remove with the comment. I only want to remove the item from my master repository of objects if no other objects have a reference to the item. Here's Collection:

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 中删除,因为没有其他集合引用它.

Notice how coworkers.remove(2) didn't remove id 2 from contactRepo? This is because it was still referenced from friends.items. However, friends.remove(4) causes id 4 to be removed from contactRepo, because no other collection is referring to it.

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

The above is what I want to do. I'm sure there are ways I can do this by keeping track of my own reference counters and such. But if there is a way to do it using javascript's built-in reference management, I'd like to hear about how to use it.

推荐答案

不,不,不,不;是的,如果你真的需要计算引用,你将不得不手动进行.JS 没有 this、GC 或弱引用的接口.

No, no, no, no; and yes, if you really need to count references you will have to do it manually. JS has no interface to this, GC, or weak references.

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

Whilst you could implement a manual reference-counted object list, it's questionable whether all the extra overhead (in performance terms but more importantly code complexity) is worth it.

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

In your example code it would seem simpler to forget the Repository, use a plain Array for your lists, and let standard garbage collection take care of dropping unused people. If you needed to get a list of all people in use, you'd just concat the friends and coworkers lists (and sort/uniquify them if you needed to).

这篇关于如何获取 javascript 对象引用或引用计数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆