Как получить ссылки на объекты javascript или количество ссылок?


как получить счетчик ссылок для объекта

  • можно ли определить, имеет ли объект javascript несколько ссылок к нему?
  • или если он имеет ссылки кроме того, что я обращаюсь к нему с?
  • или даже просто получить счетчик ссылок сам?
  • могу ли я найти эту информацию из самого javascript, или мне нужно будет отслеживать мою собственную ссылку противостоит.

очевидно, что должна быть хотя бы одна ссылка на него для моего кода доступа к объекту. Но я хочу знать, есть ли какие-либо другие ссылки на него, или если мой код является единственным местом, где он доступен. Я хотел бы иметь возможность удалить объект, если ничто другое не ссылается на него.

если вы знаете ответ, нет необходимости читать остальную часть этого вопроса. Ниже приведен только пример, чтобы сделать вещи больше четкий.


Use Case

в моем приложении, у меня есть Repository экземпляр объекта называется contacts, который содержит массив все мои контакты. Есть также несколько Collection экземпляры объектов, таких как friends коллекция и coworkers коллекция. Каждая коллекция содержит массив с различным набором элементов из contactsRepository.

Пример Кода

чтобы сделать эту концепцию более конкретной, рассмотрим код под. Каждый экземпляр 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

обратите внимание, как coworkers.remove(2) не удалил id 2 из contactRepo? Это потому, что на него все еще ссылались из friends.items. Однако,friends.remove(4) вызывает удаление идентификатора 4 из contactRepo, потому что никакая другая коллекция не ссылается на него.

резюме

выше-это то, что я хочу сделать. Я уверен, что есть способы, которыми я могу это сделать, отслеживая свою собственную ссылку счетчики и тому подобное. Но если есть способ сделать это с помощью встроенного управления ссылками javascript, я хотел бы услышать о том, как его использовать.

2 53

2 ответа:

нет, нет, нет, нет; и да, если вам действительно нужно подсчитать ссылки, вам придется сделать это вручную. JS не имеет интерфейса к этому, GC или слабым ссылкам.

во время может реализация ручного списка объектов с подсчетом ссылок, сомнительно, стоит ли все дополнительные накладные расходы (с точки зрения производительности, но что более важно, сложности кода).

в вашем примере кода, казалось бы, проще забыть Repository использовать простой Array для вашего списки, и пусть стандартная сборка мусора позаботится об удалении неиспользуемых людей. Если бы вам нужно было получить список всех людей в использовании, вы бы просто concat the friends и coworkers списки (и сортировать/унифицировать их, если вам нужно).

вам может быть интересно посмотреть на функции сокращения и массив.функции карты. карта может быть использована, чтобы помочь определить, где пересекаются ваши коллекции, или если есть пересечение вообще. Пользовательская функция reduce может использоваться как слияние (например, переопределение оператора addition, чтобы вы могли применить операцию к объектам или объединить все коллекции на "id", если это то, как вы определяете свою функцию reduce - тогда назначьте результат своему основному ссылочному массиву, я рекомендую сохранить теневой массив, который содержит все корневые объекты / значения, если вы хотите перемотать назад или что-то еще). Примечание: нужно быть осторожным с цепочками прототипов при уменьшении объекта или массива. Функция map будет очень полезна в этом случае.

Я бы предложил не чтобы удалить объект или запись, которая находится в вашем репозитории, как вы можете ссылаться на него позже. Мой подход будет заключаться в создании ShadowRepository, который будет отражать все записи / объекты, которые имеют по крайней мере одна ссылка." Из вашего описания и кода, представленного здесь, кажется, что вы инициализируете все данные и сохраняете ссылку на 1,2,4,5, как показано в вашем коде.

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

из инициализации репозитория и коллекций то, что вы просите "удалить элемент из репозитория, если на него нет ссылок", пункт 3 необходимо будет удалить немедленно. Однако вы можете отслеживать ссылки несколькими различными способами.

Я рассматривал использование Объект.наблюдайте за подобной ситуацией. Впрочем, Возражаю.наблюдать не работает во всех браузерах. Я недавно обратился к WatchJS

Я работаю над пониманием кода за Watch.JS, чтобы список наблюдателей на объекте создавался динамически, это позволило бы также удалить элемент, который больше не просматривается, хотя я предлагаю удалить ссылку в точке доступа - я имею в виду переменную, которая разделяет непосредственную лексическую область с объект, который дал единственную точку отсчета для его родного брата, может быть удален, что делает его более недоступным за пределами объекта, который предоставил запись/элемент/свойство / объект его родного брата. Со ссылкой, что все ваши другие ссылки зависят от удаленного доступа к базовым данным, останавливается. Я создаю уникальный идентификатор для ссылок на источник, чтобы избежать случайного повторного использования одного и того же.

Спасибо, что поделились своим вопросом и структурой, которую вы используете, это помог мне рассмотреть один из моих собственных конкретных случаев, когда я генерировал уникально идентифицированные ссылки на лексического брата эти уникальные идентификаторы хранились на одном объекте, который имел область действия, после прочтения здесь я пересмотрел и решил выставить только одну ссылку, а затем назначить эту ссылку на имя переменной, где когда-либо это необходимо, например, при создании наблюдателя или наблюдателя или другой коллекции.