Есть ли способ в javascript создать «слабую ссылку» на другой объект? Вот вики-страница, описывающая, что такое слабая ссылка.Вот еще одна статья, описывающая их на Java. Может кто-нибудь придумать способ реализовать это поведение в javascript?
* Официальная вики-страница спецификаций / обсуждение на wiki.ecmascript.org/doku.php?id=strawman:weak_refs, в настоящее время «Последнее изменение: 02.02.2013 22:25» * некоторые другие обсуждения спецификации на esdiscuss.org/topic/what-is-the-status-of-weak-references, в настоящее время последнее сообщение «Вс, 3 марта, 11:56:05 PST 2013»
В большинстве случаев WR - это попытка решить Проблема с задержанным слушателем, обсуждаемую здесь: [stackoverflow.com/questions/43758217/…. Если бы на этот вопрос был хороший ответ, я не думаю, что в WR было бы много нужды.
@supercat Я отправил ответ на недействительный вопрос слушателя.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


http://www.jibbering.com/faq/faq_notes/closures.html
ECMAScript использует автоматическую сборку мусора. Спецификация не определяет детали, оставляя это на усмотрение разработчиков, а некоторые реализации, как известно, дают очень низкий приоритет своим операциям по сборке мусора. Но общая идея заключается в том, что если объект становится непригодным для обращения (из-за отсутствия оставшихся ссылок на него, оставшихся доступными для выполнения кода), он становится доступным для сборки мусора и в какой-то момент в будущем будет уничтожен, а любые ресурсы, которые он потребляет, будут освобождены и возвращены. в систему для повторного использования.
Обычно это происходит при выходе из контекста выполнения. Структура цепочки областей видимости, объект Activation / Variable и любые объекты, созданные в контексте выполнения, включая объекты функций, больше не будут доступны и, следовательно, станут доступными для сборки мусора.
То есть слабых нет, есть только те, которые больше не доступны.
Избегание циклов ссылок - не единственная причина использовать слабые ссылки. Они очень удобны для объединения / кеширования экземпляров объектов и т. д.
Определение WeakReference не является вопросом. Также согласен с комментарием выше.
Обновление: с июля 2020 года в некоторых реализациях (Chrome, Edge, Firefox и Node.js) была поддержка WeakRef, как определено в Предложение WeakRefs, который по состоянию на 16 декабря 2020 года является «черновиком этапа 3».
В JavaScript нет языковой поддержки для weakrefs. Вы можете свернуть свой собственный, используя ручной подсчет ссылок, но не особенно плавно. Вы не можете создать объект-оболочку прокси, потому что в JavaScript объекты никогда не знают, когда они собираются собирать мусор.
Таким образом, ваша `` слабая ссылка '' становится ключом (например, целым числом) при простом поиске с помощью методов добавления ссылки и удаления ссылки, а когда больше нет отслеживаемых вручную ссылок, запись может быть удалена, оставив будущие поиски этот ключ для возврата null.
На самом деле это не слабая ссылка, но она может решить некоторые из тех же проблем. Обычно это делается в сложных веб-приложениях, чтобы предотвратить утечку памяти из браузеров (обычно IE, особенно более старые версии), когда существует цикл ссылок между узлом DOM или обработчиком событий и связанным с ним объектом, например закрытием. В этих случаях полная схема подсчета ссылок может даже не потребоваться.
Я внимательно не изучал (и не использовал) код, но у es-lab есть сценарий, обеспечивающий базовый Эмуляция WeakMap. Аврора 6 (Mozilla) имеет нестандартный Реализация WeakMap.
С ES6 этот ответ больше неверен. Смотрите мой ответ ниже stackoverflow.com/a/28567560/745190
Это все еще верно, потому что ES6 WeakMaps не являются истинными слабыми ссылками. WeakMaps принимает объекты только как ключи, и ссылки на эти объекты хранятся слабо. См. stackoverflow.com/questions/32397729/…
Я написал класс для имитации слабой карты и разместил его здесь: stackoverflow.com/a/47017206/491553
Просто для справки; В JavaScript этого нет, но в ActionScript 3 (который также является ECMAScript) есть. Проверьте параметр конструктора для словаря.
Истинных слабых ссылок нет, пока нет (но производители браузеров смотрят на эту тему). Но вот идея, как имитировать слабые ссылки.
Вы можете создать кеш, через который вы прогоните свои объекты. Когда объект сохраняется, кеш сохраняет прогноз того, сколько памяти займет объект. Для некоторых элементов, таких как хранение изображений, это легко решить. Для других это было бы труднее.
Когда вам нужен объект, вы затем запрашиваете его у кеша. Если в кеше есть объект, он возвращается. Если его там нет, то элемент создается, сохраняется, а затем возвращается.
Слабые ссылки моделируются путем удаления элементов кэша, когда общий объем прогнозируемой памяти достигает определенного уровня. Он предскажет, какие элементы используются меньше всего, в зависимости от того, как часто они извлекаются, с учетом того, как давно они были извлечены. «Расчетная» стоимость также может быть добавлена, если код, создающий элемент, передается в кеш в качестве закрытия. Это позволит кешу хранить элементы, создание или создание которых очень дорогое.
Алгоритм удаления является ключевым, потому что, если вы ошибетесь, вы можете удалить самые популярные элементы. Это привело бы к ужасной производительности.
Пока кеш является единственным объектом со ссылками постоянный на сохраненные объекты, указанная выше система должна работать довольно хорошо как альтернатива истинным слабым ссылкам.
Разве большая часть того, что вы сказали, не имеет отношения к weakrefs?
@ErikAllik Чаще всего слабые ссылки используются для хранения больших объемов данных и их удаления, если у вас заканчивается место. Я описал способ подделать это, автоматически отслеживая память самостоятельно и удаляя элементы, когда они больше не нужны.
@ JL235 - слабые ссылки важны не для кешей, а для обработчиков событий. У меня есть объект, который, пока существует, должен наблюдать какое-то другое событие, но я не хочу, чтобы тот факт, что он находится в списке уведомлений, составлял ссылку для целей GC.
@Malvolio: Я успешно использовал слабые ссылки для кешей в Java, и они хорошо работают.
Слабые ссылки не имеют ничего общего с кешированием. Слабая ссылка означает, что вы хотите что-то отслеживать, но если не осталось ссылок на отслеживаемый объект, вы разрешаете его удаление.
Очевидно, что есть вариант использования для создания кеша с использованием слабых ссылок для автоматического истечения срока действия.
+1. Использование слабых ссылок с кешированием имеет смысл при описанном здесь способе. К сожалению, это невозможно с JS, поэтому описанный вами подход кажется лучшей альтернативой и, возможно, даже лучше, чем использование слабых ссылок, поскольку он дает больше контроля за счет более явной реализации.
Кеширование традиционно является основной причиной слабых ссылок. Обработчик событий DOM - это всего лишь некоторая ошибка IE Explorer.
При запуске JS на NodeJS вы можете рассмотреть https://github.com/TooTallNate/node-weak.
EcmaScript 6 (ES Harmony) имеет объект WeakMap. Поддержка браузеров среди современных браузеров - довольно хорошо (последние 3 версии Firefox, Chrome и даже будущая версия IE поддерживают его).
Это не совсем то же самое. WeakMap не дает слабых ссылок на объекты - это не значения, которые являются слабыми ссылками в WeakMap, а ключи. Тот факт, что на карте существуют слабые ссылки, - это только механизм предотвращения утечки памяти, и в противном случае пользователь не может наблюдать их.
Вы правы, что слабые ключи, а не значения. Но вся цель использования слабых ссылок - разрешить сборку мусора для указанного объекта. OP опубликовал две ссылки, вторая из которых касается добавления идентификатора к объекту, который вы не можете расширить, и на самом деле он рекомендует использовать WeakHashMap, Java-эквивалент WeakMap в JavaScript.
удачи в использовании WeakMap для реализации слабой ссылки, поскольку weakmap.get(new String('any possible key that has ever existed or ever will exist')) будет всегда быть undefined. Нет полезно. Голосование против!
Использование механизма кэширования для имитации слабой ссылки, как 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
Как владелец ссылки, вы не должны делать никаких предположений о том, когда она относится к значению, это не отличается от использования кеша.
Наконец-то они здесь. Еще не реализовано в браузерах, но скоро будет.
Пока что нельзя использовать слабые ссылки, но, скорее всего, скоро это станет возможно, так как Слабые ссылки в JavaScript находятся в стадии разработки. Подробности ниже.
Предложение сейчас в 3 этап, что означает, что он имеет полный Спецификация и что дальнейшее уточнение потребует обратной связи от реализаций и пользователей.
Предложение WeakRef включает в себя две основные новые функциональные возможности:
основное использование для слабых ссылок предназначен для реализации кешей или сопоставлений, содержащих большие объекты, где желательно, чтобы большой объект не поддерживался в рабочем состоянии только потому, что он появляется в кэше или отображении.
Доработка - это выполнение кода для очистки после объекта, который стал недоступен для выполнения программы. Определяемые пользователем финализаторы позволяют использовать несколько новых вариантов использования и могут помочь предотвратить утечки памяти при управлении ресурсами, о которых сборщик мусора не знает.
https://github.com/tc39/proposal-weakrefs
https://v8.dev/features/weak-references
Firefox Nightly добавил экспериментальную поддержку WeakRef. Вот пример реализации, использующей его для создания итеративной версии WeakSet: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
2021 Обновление
WeakRef теперь реализован в Chrome, Edge и Firefox. Все еще ждем Safari и некоторых других противников.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
Обсуждаются слабые ссылки для ES6. Не спускайте глаз с глаз.