How to get links to javascript objects or number of links?

How to get a reference counter for an object

  • Is it possible to determine if a javascript object has multiple links ?
  • Or, if he has links other than the one to which I refer to him using ?
  • Or even just get a reference count ?
  • Can I find this information from javascript itself, or will I need to track my own link counts.

Obviously, for my code, there must be at least one link to access the object. But I want to know if there are any other links to it, or if my code is the only place it accesses. I would like to be able to delete an object if nothing refers to it.

If you know the answer, there is no need to read the rest of this question. The following is an example to make things clearer.




Use case

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

Code example

To make this concept more specific, consider the code below. Each instance of the Repository object contains a list of all elements of a particular type. You can have a Contacts repository and a separate Events repository. To make it simple, you can simply add, add and remove elements and add them through 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; } } } 

Notice the line in remove with the comment. I want to remove an object from my main object store if no other objects reference the element. Here 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; } } } 

And then this code uses Repository and 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 

Note that coworkers.remove(2) not removed id 2 from contactRepo? This is because it still refers to friends.items . However, friends.remove(4) causes id 4 to be removed from contactRepo , because no other collection references it.

Summary

Above was what I want to do. I am sure there are ways to do this by tracking my own link counts, etc. But if there is a way to do this using the built-in javascript link management, I would like to know how to use it.

+51
javascript garbage-collection reference
May 30 '10 at 12:45 a.m.
source share
2 answers

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

While you can implement a list of objects with reference counting manually, it is doubtful whether all the extra overhead is worth it (in terms of performance, but more importantly, the complexity of the code).

In your code example, it would be easier to forget the Repository , use a simple Array for your lists and let the standard garbage collection take care of removing unused people. If you need a list of all users, you just concat friends and coworkers lists (and sort / define them if you need to).

+15
May 30 '10 at 1:31
source share

You may need to learn the reduction functions and the array.map functions. a map can be used to help determine where your collections intersect, or if there is an intersection at all. The user-defined shortening function can be used as a merge (like overriding the addition operator so that you can apply the operation to objects or merge all collections into "id" if that is how you define the shortening function), then assign the result to your main array of links, I recommend store a shadow array that contains all the root objects / values ​​in case you want REWIND or something else). Note. When reducing an object or array, you need to be careful with prototype chains. In this case, the display function will be very useful.

I would suggest not deleting the object or record located in your repository, as you may want to refer to it later. My approach would be to create a ShadowRepository that would reflect all the records / objects that have at least one β€œlink”. From the description and code given here, you see that you initialize all the data and keep the link to 1,2,4,5, as shown in your code.

 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) ]); 

From the initialization of the repository and collections that you ask "Delete an item from the repository if there are no links to it", item 3 will need to be deleted immediately. However, you can track links in several ways.

I considered using Object.observe for a similar situation. However, Object.observe does not work in all browsers. I recently turned to WatchJS

I am working on an understanding of the code behind Watch.JS to allow the dynamic creation of a list of observers on an object, which will remove an item that is no longer being viewed, although I suggest deleting the link to the access point. What I mean is a variable that shares the immediate lexical region with the object that provided the only reference to it, can be deleted, which makes it no longer available outside the object that exposed the entry / element / property / object of this sibling. With a link to the fact that all your other links depend on remote access to the underlying data, it stops. I generate a unique identifier for the source links to avoid accidentally reusing the same one.

Thank you for sharing your question and the structure that you are using, it helped me consider one of my specific cases when I created uniquely identified references to the lexical brother, these unique identifiers were stored on the ONE object that had the area. After reading here I changed my mind and decided to expose only one link, and then assign this link to the name of the variable where it will ever be needed, for example, when creating an observer or observer or another collection.

+1
Jul 17 '16 at 22:34
source share



All Articles