Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get javascript object references or reference count?

How to get reference count for an object

  • Is it possible to determine if a javascript object has multiple references to it?
  • Or if it has references besides the one I'm accessing it with?
  • Or even just to get the reference count itself?
  • Can I find this information from javascript itself, or will I need to keep track of my own reference counters.

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.


Use Case

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.

Sample Code

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;     }   } }   

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;     }   } } 

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 

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.

Summary

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.

like image 634
Tauren Avatar asked May 30 '10 00:05

Tauren


People also ask

Does JavaScript store by reference or value?

The Bottom Line on JavaScript ReferencesOn variable assignment, the scalar primitive values (Number, String, Boolean, undefined, null, Symbol) are assigned-by-value and compound values are assigned-by-reference. The references in JavaScript only point at contained values and NOT at other variables, or references.

How many references and objects are created?

You have up to three references to two different objects. Note: unless your code does something useful with them the JVM can optimise this code away to nothing, in which case you will have no references or objects.

Are JavaScript objects references?

In JavaScript, objects are a reference type. Two distinct objects are never equal, even if they have the same properties. Only comparing the same object reference with itself yields true.


1 Answers

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.

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).

like image 53
bobince Avatar answered Sep 19 '22 06:09

bobince