问题描述
- 是否可以确定一个 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.
在我的应用程序中,我有一个名为 contacts
的 Repository
对象实例,其中包含 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;
}
}
}
然后这段代码使用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
中删除,因为没有其他集合引用它.
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
friends
和 coworkers
列表(并对它们进行排序/唯一化如果需要).
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 对象引用或引用计数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!