programing

자바 스크립트 객체 참조 또는 참조 횟수를 얻는 방법은 무엇입니까?

firstcheck 2021. 1. 16. 09:53
반응형

자바 스크립트 객체 참조 또는 참조 횟수를 얻는 방법은 무엇입니까?


개체에 대한 참조 횟수를 얻는 방법

  • 자바 스크립트 개체에 여러 참조 가 있는지 확인할 수 있습니까?
  • 또는 내가 액세스하는 것 외에 참조가 있다면 ?
  • 아니면 참조 횟수 자체 를 얻기 위해 ?
  • 자바 스크립트 자체에서이 정보를 찾을 수 있습니까, 아니면 자체 참조 카운터를 추적해야합니까?

분명히 내 코드가 개체에 액세스하려면 적어도 하나의 참조가 있어야합니다. 그러나 내가 알고 싶은 것은 그것에 대한 다른 참조가 있는지 또는 내 코드가 액세스되는 유일한 장소인지 여부입니다. 아무것도 참조하지 않는 경우 개체를 삭제할 수 있기를 원합니다.

답을 안다면이 질문의 나머지 부분을 읽을 필요가 없습니다. 아래는 일을 더 명확하게하기위한 예입니다.


사용 사례

내 응용 프로그램 에는 모든 연락처 의 배열을 포함하는 Repository개체 인스턴스 contacts가 있습니다 . 컬렉션 및 컬렉션과 같은 여러 개체 인스턴스 있습니다. 각 컬렉션에는 .Collectionfriendscoworkerscontacts 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;
    }
  }
}  

주석이있는 줄 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

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.


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


You may interest to look into reduce functions, and array.map functions. map could be used to help identify where your collections intersect, or if there is an intersection at all. A user defined reduce function could be used like a merge (kinda like overriding the addition operator so that you can apply operation to objects, or merge all collections on "id" if that is how you define your reduce function - then assign the result to your master reference array, I recommend keeping a shadow array that holds all of the root object/values in case you would like to REWIND or something). Note: one must be careful of prototype chains when reducing an object or array. The map function will be very helpful in this case.

I would suggest not to remove the object or record that is in your Repository as you may want to reference it again later. My approach would be to create a ShadowRepository that would reflect all records/objects that have at least one "Reference". From your description and code presented here it appears you are initializing all of the data and storing reference to 1,2,4,5 as appears 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 the collections, what you are asking "Remove item from repository if there are no references to it" item 3 would need to be removed immediatly. You can however track the references in a few different ways.

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

I am working on understanding the code behind Watch.JS to allow a list of observers on an object to be created dynamically this would allow one to also remove an item that is no longer watched, though I suggest to remove the reference at the point of access - What I mean is a variable that shares the immediate lexical scope with an object that has given a single point of reference to it's sibling can be removed making it no longer accessable outside of the object that had exposed the record/item/property/object of it's sibling. With the reference that all of your other references depended on removed access to the underlying data is stopped. I am generating unique id for origin references to avoid accidentally reusing the same one.

Thank you for sharing your question and the structure you are using, it has helped me consider one of my own specific cases where I was generating uniquely identified references to a lexical sibling these unique ids were kept on the ONE object that had scope, After reading here I have reconsidered and decided to expose only one reference then assign that reference to a variable name where ever it is needed such as in creating a watcher or observer or other Collection.

ReferenceURL : https://stackoverflow.com/questions/2937120/how-to-get-javascript-object-references-or-reference-count

반응형