Можно ли создать «слабую ссылку» в javascript?

98

Есть ли способ в javascript создать «слабую ссылку» на другой объект? Вот вики-страница, описывающая, что такое слабая ссылка. Вот еще одна статья, описывающая их на Java. Может ли кто-нибудь придумать способ реализовать такое поведение в javascript?

Стивен Кейгл
источник
4
Обсуждаются слабые ссылки для ES6. Следите за глазами.
Райан Смит
2
* Официальная вики-страница спецификаций / обсуждение на wiki.ecmascript.org/doku.php?id=strawman:weak_refs , в настоящее время «Последнее изменение: 02.02.2013, 22:25» * другие обсуждения спецификации на esdiscuss.org/topic/what -is-the-status-of-weak- links, в настоящее время последнее сообщение «3 марта, воскресенье, 11:56:05 по тихоокеанскому времени, 2013 г.»
Destiny Architect
В большинстве случаев WRS является попыткой решить Lapsed Приёмник проблему , обсуждаются здесь: [ stackoverflow.com/questions/43758217/... . Если бы на этот вопрос был хороший ответ, я не думаю, что в WR было бы много нужды.
Джеймс

Ответы:

39

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

Таким образом, ваша `` слабая ссылка '' становится ключом (например, целым числом) в простом поиске с помощью методов добавления ссылки и удаления ссылки, а когда больше нет отслеживаемых вручную ссылок, запись может быть удалена, оставив будущие поиски на этот ключ для возврата null.

На самом деле это не слабая ссылка, но она может решить некоторые из тех же проблем. Обычно это делается в сложных веб-приложениях, чтобы предотвратить утечку памяти из браузеров (обычно IE, особенно старые версии), когда существует цикл ссылок между узлом DOM или обработчиком событий и связанным с ним объектом, например закрытием. В этих случаях полная схема подсчета ссылок может даже не потребоваться.

бобинс
источник
2
Я не изучал (и не использовал) код внимательно, но у es-lab есть сценарий, обеспечивающий базовую эмуляцию WeakMap . Aurora 6 (Mozilla) имеет нестандартную реализацию WeakMap .
theazureshadow
2
С ES6 этот ответ больше неверен. См. Мой ответ ниже stackoverflow.com/a/28567560/745190
thelastshadow
9
Это по-прежнему правильно, потому что ES6 WeakMaps не являются настоящими слабыми ссылками. WeakMaps принимает объекты только как ключи, и ссылки на эти объекты хранятся слабо. См stackoverflow.com/questions/32397729/...
CodeManX
Я написал класс для имитации слабой карты и разместил его здесь: stackoverflow.com/a/47017206/491553
Райан Шиллингтон
11

Обновление: сентябрь 2019 г.

Пока что невозможно использовать слабые ссылки, но, скорее всего, скоро это станет возможным, поскольку WeakRefs в JavaScript находятся в стадии разработки . Подробности ниже.

Предложение

Предложение находится в стадии 3, что означает, что оно имеет полную спецификацию и что дальнейшее уточнение потребует обратной связи от реализаций и пользователей.

Предложение WeakRef включает в себя две основные новые функциональные возможности:

  • Создание слабых ссылок на объекты с помощью класса WeakRef
  • Запуск определяемых пользователем финализаторов после сборки объектов с помощью класса FinalizationGroup

Сценарии использования

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

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

Источник и дальнейшее чтение

https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references

М. Тварог
источник
1
Firefox Nightly добавил экспериментальную поддержку WeakRef. Вот пример реализации, использующей его для создания итеративной версии WeakSet: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley
3

Настоящих слабых ссылок нет, пока нет (но производители браузеров смотрят на эту тему). Но вот идея, как имитировать слабые ссылки.

Вы можете создать кеш, через который вы прогоните свои объекты. Когда объект сохраняется, кеш сохраняет прогноз того, сколько памяти займет объект. Для некоторых элементов, таких как хранение изображений, это легко решить. Для других это было бы труднее.

Когда вам нужен объект, вы запрашиваете его у кеша. Если в кеше есть объект, он возвращается. Если его нет, то элемент создается, сохраняется, а затем возвращается.

Слабые ссылки моделируются путем удаления элементов кэша, когда общий объем прогнозируемой памяти достигает определенного уровня. Он предскажет, какие элементы используются меньше всего, на основе того, как часто они извлекаются, с учетом того, как давно они были извлечены. «Расчетная» стоимость также может быть добавлена, если код, создающий элемент, передается в кеш в качестве закрытия. Это позволит хранить в кеше элементы, создание и создание которых очень дорогое.

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

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

JL235
источник
25
Разве большая часть того, что вы сказали, не имеет отношения к weakrefs?
Эрик Каплун
22
@ JL235 - слабые ссылки используются не в кэшах, а в обработчиках событий. У меня есть объект, который, пока существует, должен наблюдать какое-то другое событие, но я не хочу, чтобы тот факт, что он находится в списке уведомлений, составлял ссылку для целей GC.
Мальволио
7
Слабые ссылки не имеют ничего общего с кешированием. Слабая ссылка означает, что вы хотите что-то отслеживать, но если не осталось ссылок на отслеживаемый объект, вы разрешаете его удаление.
fabspro
8
Очевидно, что существует вариант использования для создания кеша с использованием слабых ссылок для автоматического истечения срока действия.
Фил Фриман,
5
Кеширование традиционно является основной причиной слабых ссылок. Обработчик событий DOM - это всего лишь ошибка IE Explorer.
axkibe
2

Использование механизма кэширования для имитации слабой ссылки, как было предложено выше в JL235 , является разумным. Если бы слабые ссылки существовали изначально, вы бы наблюдали подобное поведение:

this.val = {};
this.ref = new WeakReference(this.val);
...
this.ref.get(); // always returns val
...
this.val = null; // no more references
...
this.ref.get(); // may still return val, depending on already gc'd or not

В то время как с кешем вы бы наблюдали:

this.val = {};
this.key = cache.put(this.val);
...
cache.get(this.key); // returns val, until evicted by other cache puts
...
this.val = null; // no more references
...
cache.get(this.key); // returns val, until evicted by other cache puts

Как владелец ссылки, вы не должны делать никаких предположений о том, когда она ссылается на значение, это не отличается от использования кеша.

Маркус
источник
-4

EcmaScript 6 (ES Harmony) имеет объект WeakMap . Браузерная поддержка среди современных браузеров довольно хороша (последние 3 версии Firefox, Chrome и даже будущая версия IE поддерживают ее).

последняя тень
источник
29
Это не совсем то же самое. A WeakMapне дает слабых ссылок на объекты - слабыми ссылками в WeakMap являются не значения , а ключи . Тот факт, что на карте существуют слабые ссылки, - это только механизм предотвращения утечки памяти, и в противном случае пользователь не видит их.
EyasSH
1
Вы правы, что слабые ключи, а не значения. Но вся цель использования слабых ссылок - разрешить сборку мусора для указанного объекта. OP опубликовал две ссылки, вторая из которых касается добавления идентификатора к объекту, который вы не можете расширить, и на самом деле он рекомендует использовать WeakHashMap, Java-эквивалент WeakMap в JavaScript.
thelastshadow
12
удачи в использовании WeakMap для реализации слабой ссылки, так weakmap.get(new String('any possible key that has ever existed or ever will exist'))как всегда будет undefined. Не полезно. Голосование против!
user3338098
-5

http://www.jibbering.com/faq/faq_notes/closures.html

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

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

То есть слабых нет, есть только те, которые больше не доступны.

ветвь
источник
10
Избегание циклов ссылок - не единственная причина использовать слабые ссылки. Они очень удобны для объединения / кеширования экземпляров объектов и т. Д.
пушистый
Определение WeakReference не является вопросом. Также согласен с комментарием выше.
Юрий Ярышев