Чи можливо створити "слабку посилання" в JavaScript?


97

Чи є в JavaScript можливість створити "слабку посилання" на інший об'єкт? Ось сторінка вікі з описом того, що таке слабке посилання. Ось ще одна стаття, яка описує їх на Java. Чи може хтось придумати спосіб реалізувати цю поведінку в JavaScript?


4
Обговорюються слабкі посилання на ES6. Тримайте очі очищеними.
Райан Сміт

2
* Офіційна специфікація wiki / обговорення на wiki.ecmascript.org/doku.php?id=strawman:weak_refs , в даний час "Остання зміна: 02.02.2013 22:25" * деякі інші специфічні дискусії на esdiscuss.org/topic/what -is-the-status-of-слабкі посилання , в даний час останнє повідомлення "Вс 3 березня 11:56:05 PST 2013"
Destiny Architect

У більшості випадків WR - це спроба вирішити проблему слухача пропущеного слухача , обговорювану тут: [ stackoverflow.com/questions/43758217/… . Якби на це запитання була хороша відповідь, я не думаю, що було б багато необхідності в WR.
Джеймс

Відповіді:


39

Немає мовної підтримки для слабких файлів у JavaScript. Ви можете прокрутити свій власний, використовуючи ручний підрахунок посилань, але не особливо плавно. Ви не можете створити об’єкт обгортки проксі, тому що в JavaScript об’єкти ніколи не знають, коли вони збираються збирати сміття.

Таким чином, ваша "слабка посилання" стає ключем (наприклад, цілим числом) у простому пошуку, з методом додавання довідки та видалення-посилання, а коли вже немає посилань, відслідковуваних вручну, запис можна видалити, залишаючи майбутні огляди на цей ключ для повернення нуля.

Це насправді не слабке місце, але воно може вирішити деякі ті самі проблеми. Зазвичай це робиться в складних веб-додатках для запобігання витоку пам’яті з браузерів (як правило, IE, особливо старіших версій), коли між вузлом DOM або обробником подій є об'єктом посилання та об'єктом, пов’язаним з ним, таким як закриття. У цих випадках повна схема підрахунку довідок може навіть не знадобитися.


2
Я ретельно не вивчав (або використовував) код, але в es-lab є сценарій, що забезпечує основну емуляцію слабкої карти . Aurora 6 (Mozilla) має нестандартну реалізацію слабких карт .
theazureshadow

2
З ES6 ця відповідь більше не є правильною. Дивіться мою відповідь нижче stackoverflow.com/a/28567560/745190
thelastshadow

9
Це все ще правильно, тому що ES6 WeakMaps не є справжніми слабкими посиланнями. Слабкі карти приймають об'єкти лише як ключі, і посилання на ці об'єкти зберігаються слабо. Див stackoverflow.com/questions/32397729 / ...
CodeManX

Я написав клас для імітації слабкої карти та розмістив його тут: stackoverflow.com/a/47017206/491553
Райан Шилінгтон


11

Оновлення: вересень 2019 року

Поки що неможливо використовувати слабкі посилання, але, швидше за все, незабаром це стане можливим, оскільки WeakRefs в JavaScript - це робота в процесі роботи. Деталі нижче.

Пропозиція

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

Пропозиція WeakRef включає два основні нові функції:

  • Створення слабких посилань на об'єкти з класом WeakRef
  • Запуск визначених користувачем фіналізаторів після збирання сміття з класом FinalizationGroup

Використовуйте випадки

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

Фіналізація - це виконання коду для очищення після об'єкта, який став недоступним для виконання програми. Зазначені користувачем фіналізатори дозволяють отримати кілька нових випадків використання та можуть запобігти витоку пам’яті під час керування ресурсами, про які збирач сміття не знає.

Джерело та подальше читання

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


1
Firefox Nightly додав експериментальну підтримку для WeakRef. Ось приклад реалізації, використовуючи його для створення ітерабельної версії WeakSet: gist.github.com/seanlinsley/bc10378fd311d75cf6b5e80394be813d
seanlinsley

3

Справжні слабкі посилання, ні, ще немає (але виробники браузерів дивляться на тему). Але ось ідея про те, як імітувати слабкі посилання.

Ви можете створити кеш, через який ви керуєте своїми об'єктами. Коли об’єкт зберігається, кеш зберігає передбачення, скільки пам'яті займе об'єкт. Для деяких предметів, як-от зберігання зображень, це прямо вперед. Для інших це було б складніше.

Коли вам потрібен об'єкт, ви запитуєте його кеш. Якщо в кеші є об'єкт, він повертається. Якщо його немає, то елемент генерується, зберігається та повертається.

Слабі посилання моделюються елементами видалення кеша, коли загальна кількість передбачуваної пам'яті досягне певного рівня. Він спрогнозує, які предмети найменше використовуються, виходячи з того, як часто їх витягують, зваживши на те, як давно їх вивезли. Вартість "розрахунку" також може бути додана, якщо код, який створює елемент, передається в кеш як закриття. Це дозволить кешу зберігати елементи, які дуже дорого створювати або генерувати.

Алгоритм видалення є ключовим, тому що якщо ви помилитесь, тоді ви зможете видалити найпопулярніші елементи. Це призвело б до страшної роботи.

Поки кеш є єдиним об'єктом, який має постійні посилання на об'єкти, що зберігаються, тоді вищевказана система повинна працювати досить добре, як альтернатива справжнім слабким посиланням.


25
Хіба більшість того, що ви сказали, не має відношення до слабких рефлексів?
Ерік Каплун

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, хром і навіть майбутня версія IE підтримують це).


29
Це не зовсім те саме. WeakMapНе дають слабкі посилання на objects-- це не цінності , які є слабкими посиланнями в WeakMap, але ключі . Той факт, що на карті існують слабкі посилання, є лише механізмом запобігання витоку пам’яті, а користувач не може спостерігати інакше.
EyasSH

1
Ви правильні, що ключові слова слабкі, а не значення. Але вся мета використання слабких посилань - дозволити збирання сміття згаданого об'єкта. ОП розмістила два посилання, друге з яких стосується додавання ідентифікатора до об'єкта, який ви не можете розширити, і насправді рекомендує використовувати WeakHashMap, Java-еквівалент WeakMap JavaScript.
thelastshadow

12
удачі, використовуючи WeakMap для впровадження слабкого посилання, оскільки weakmap.get(new String('any possible key that has ever existed or ever will exist'))це завжди буде undefined. Не корисно. Вниз голосування!
користувач3338098

-5

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

ECMAScript використовує автоматичний збір сміття. У специфікації не визначені деталі, що залишає це для розробників, щоб розібратися, а деякі реалізації, як відомо, надають дуже низький пріоритет своїм операціям з вивезення сміття. Але загальна ідея полягає в тому, що якщо об’єкт стає нерециркульованим (не маючи інших посилань на нього, залишається доступним для виконання коду), він стає доступним для збору сміття і в якийсь майбутній момент буде знищений, а будь-які ресурси, які він споживає, звільняються і повертаються до системи для повторного використання.

Зазвичай це стосується виходу із контексту виконання. Структура ланцюга діапазону, об'єкт активації / змінної та будь-які об'єкти, створені в контексті виконання, включаючи функціональні об'єкти, більше не будуть доступні і тому стануть доступними для збору сміття.

Тобто слабких немає лише тих, які більше не стають доступними.


10
Уникання циклів відліку не є єдиною причиною використання слабких посилань. Вони дуже зручні для об’єднання об’єктів об'єктів / кешування тощо.
пухнастий

Визначення WeakReference не є питанням. Також, як згоден з коментарем вище
Юрій Яришев
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.