Tau*_*ren 54 javascript garbage-collection reference
显然,对于我的代码访问对象,必须至少有一个引用它.但我想知道的是,是否有任何其他引用,或者我的代码是唯一访问它的地方.如果没有别的东西引用它,我希望能够删除该对象.
如果您知道答案,则无需阅读本问题的其余部分.以下只是一个让事情更加清晰的例子.
在我的应用程序中,我有一个Repository名为的对象实例contacts,其中包含所有联系人的数组.还有多个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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意注释中的行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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后此代码使用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
Run Code Online (Sandbox Code Playgroud)
请注意,如何coworkers.remove(2)从contactRepo中删除id 2?这是因为它仍然被引用friends.items.但是,friends.remove(4)导致id 4被删除contactRepo,因为没有其他集合引用它.
以上是我想做的.我确信通过跟踪我自己的参考计数器等,我可以做到这一点.但如果有办法使用javascript的内置参考管理,我想听听如何使用它.
bob*_*nce 16
不不不不; 是的,如果你真的需要计算参考,你必须手动完成.JS没有与此,GC或弱引用的接口.
虽然您可以实现手动引用计数对象列表,但是所有额外开销(在性能方面,但更重要的是代码复杂性)是否值得,这是值得怀疑的.
在您的示例代码中,忘记Repository使用简单文件,使用普通文件Array列表,并让标准垃圾收集处理丢弃未使用的人员似乎更简单.如果你需要获得所有正在使用的人的列表,你只concat需要friends和coworkers列表(如果需要,可以对它们进行排序/统一).