如何获取对象的引用计数
- 能否确定一个JavaScript对象是否有多个引用?
- 或者它是否有除我访问时的引用外的其他引用?
- 甚至只是获取引用计数本身?
- 我能否从JavaScript本身中找到这些信息,还是需要跟踪自己的引用计数器。
显然,我的代码访问该对象时,必须至少存在一个引用。但是我想知道的是是否还有其他对它的引用,或者我的代码是唯一访问它的地方。如果没有其他地方引用它,我希望能够删除该对象。
如果您知道答案,无需阅读此问题的其余部分。下面只是一个示例,以使事情更加清晰。
用例
在我的应用程序中,我有一个名为contacts
的Repository
对象实例,其中包含所有联系人的数组。还有多个Collection
对象实例,例如friends
集合和coworkers
集合。每个集合都包含来自contacts
Repository
的不同数据项集合。
示例代码
为了使这个概念更加具体,考虑下面的代码。每个Repository
对象实例都包含特定类型的所有项列表。您可能有一个联系人Contacts的存储库和一个独立的事件Events的存储库。为了保持简单,您可以只获取、添加和删除项目,并通过构造函数添加许多项目。
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
中的那行代码注释。我只想在没有其他对象引用该项的情况下,从我的主存储库中删除该项。以下是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;
}
}
}
然后这段代码使用 Repository
和 Collection
:
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内置的引用管理的方法,我想知道如何使用它。
Collection
实例引用它时,我想从Repository
中删除一个项目。因此,常规的垃圾回收在这里不起作用,因为该项目仍然存在于Repository
中。我必须知道对象是否仍在某个地方使用,这就是为什么我创建了一个存储所有正在使用的对象引用的存储库对象。 - Tauren