aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/global_objects/weakmap/index.html
blob: 9b1f77b853fd4f41c6a6ba0d92041ac2d34313ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
---
title: WeakMap
slug: Web/JavaScript/Reference/Global_Objects/WeakMap
translation_of: Web/JavaScript/Reference/Global_Objects/WeakMap
---
<div>{{JSRef("Global_Objects", "WeakMap")}}</div>

<h2 id="Сводка">Сводка</h2>

<p>Объект <strong><code>WeakMap</code></strong> — коллекция пар ключ-значение. В качестве ключей могут быть использованы только объекты, а значения могут быть произвольных типов.</p>

<h2 id="Syntax">Синтаксис</h2>

<pre class="syntaxbox notranslate"><code>new WeakMap([iterable])
</code></pre>

<h3 id="Parameters">Параметры</h3>

<dl>
 <dt><code>iterable</code></dt>
 <dd>Может быть массивом или любым другим итерируемым объектом, элементы которого являются парами ключ-значение (массивы из двух элементов). Каждая пара ключ-значение будет добавлена во вновь созданный экземпляр <code>WeakMap</code>. <code>Null</code> обрабатывается как <code>undefined</code>.</dd>
</dl>

<h2 id="Description">Описание</h2>

<p>Ключами WeakMap могут быть только объекты. {{Glossary("Primitive", "Примитивы")}} в качестве ключей не допускаются (т.е. {{jsxref("Symbol")}} не может быть ключом <code>WeakMap</code>).</p>

<h3 id="Почему_WeakMap">Почему<em> Weak</em>Map?</h3>

<p>Опытный JavaScript разработчик заметит, что map API можно реализовать на JavaScript c помощью двух массивов (один для ключей, второй для значений) и четырёх общих API методов. Установка элементов в этот map должна будет одновременно запушить ключи и значения. В результате индексы ключа и значения будут корректными. Получение значений с map потребует итерирование ключей, чтобы найти совпадение, а затем использование индекса этого соответствия для извлечения соответствующего значения из массива значений.</p>

<p>У такой реализации было бы два главных неудобства. Первым является O(n) поиск (где n — количество ключей в map), так как обе операции требуют итерирование списка ключей для нахождения совпадения. Вторым <span style="background-color: #f9f9f9; color: #252525; font-family: sans-serif; font-size: 12.3199996948242px; line-height: 18.4799995422363px; text-transform: lowercase;">– </span>проблема утечки памяти. В словарях, написанных вручную, массив с ключами будет хранить ссылки на объекты-ключи, не давая им быть помеченными сборщиком мусора. В нативных <code>WeakMap</code>, ссылки на объекты-ключи хранятся «слабо», что означает то, что они не предотвратят сборку мусора в том случае, если других ссылок на объект не будет.</p>

<p>WeakMaps имеют “weak” («слабые») обращения к ключам объекта, а следовательно непрепятствие сборщику мусора, когда мы больше не имеем объекта-ключа. WeakMaps могут быть особенно полезными конструкциями при сопоставлении ключей с информацией о ключе, который ценен, только если ключ не был собран сборщиком мусора (Garbage collector).</p>

<p>Из-за того, что ссылки являются слабыми, ключи <code>WeakMap</code> не перечисляемы (то есть нет метода, который возвращает список ключей). Иначе список бы зависел от состояния сбора мусора, представляя индетерминизм. Если вы хотите иметь список ключей, вам следует поддерживать его самостоятельно.</p>

<h2 id="Properties">Свойства</h2>

<dl>
 <dt><code>WeakMap.length</code></dt>
 <dd>Значение свойства <code>length</code> всегда равно 0.</dd>
 <dt>{{jsxref("WeakMap.prototype")}}</dt>
 <dd>Представляет прототип конструктора <code>WeakMap</code>. Позволяет добавлять свойства всем объектам типа <code>WeakMap</code>.</dd>
</dl>

<h2 id="Boolean_instances">Экземпляры <code>WeakMap</code></h2>

<p>Все экземпляры <code>WeakMap</code> унаследованы от {{jsxref("WeakMap.prototype")}}.</p>

<h3 id="Свойства">Свойства</h3>

<p>{{page('ru/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Properties')}}</p>

<h3 id="Методы">Методы</h3>

<p>{{page('ru/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Methods')}}</p>

<h2 id="Примеры">Примеры</h2>

<h3 id="Использование_объекта_WeakMap">Использование объекта <code>WeakMap</code></h3>

<pre class="brush: js notranslate">const wm1 = new WeakMap(),
    wm2 = new WeakMap(),
    wm3 = new WeakMap();
const o1 = {},
    o2 = function(){},
    o3 = window,
    o4 = [1, 2, 3];

wm1.set(o1, 37);
wm1.set(o2, 'azerty');
wm2.set(o1, o2);        // значением может быть что угодно, включая объект или функцию
wm2.set(o3, undefined);
wm2.set(wm1, wm2);      // ключами и значениями могут быть объекты. Даже WeakMap-ами

wm1.get(o2); // 'azerty'
wm2.get(o2); // undefined, нет значения для o2 в wm2
wm2.get(o3); // undefined, это установленное значение

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (даже если значение равно 'undefined')

wm3.set(o1, 37);
wm3.get(o1);     // 37

wm1.has(o1);     // true
wm1.delete(o1);
wm1.has(o1);     // false
</pre>

<h3 id="Пример_Реализация_класса_WeakMap-like_классов_с_методом_.clear">Пример: Реализация класса WeakMap-like классов с методом .clear()</h3>

<pre class="brush: js notranslate">class ClearableWeakMap {
    constructor(init) {
        this._wm = new WeakMap(init)
    }
    clear() {
        this._wm = new WeakMap()
    }
    delete(k) {
        return this._wm.delete(k)
    }
    get(k) {
        return this._wm.get(k)
    }
    has(k) {
        return this._wm.has(k)
    }
    set(k, v) {
        this._wm.set(k, v)
        return this
    }
}
</pre>

<h2 id="Спецификации">Спецификации</h2>

<table>
 <thead>
  <tr>
   <th scope="col">Спецификация</th>
   <th scope="col">Статус</th>
   <th scope="col">Комментарий</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>{{SpecName('ES2015', '#sec-weakmap-objects', 'WeakMap')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Изначальное определение.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-weakmap-objects', 'WeakMap')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<p style=""></p>

<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>

<p>{{Compat("javascript.builtins.WeakMap")}}</p>

<h2 id="Смотрите_также">Смотрите также</h2>

<p style=""></p>

<ul>
 <li><a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=547941">WeakMap bug at Mozilla</a></li>
 <li><a href="http://fitzgeraldnick.com/weblog/53/">Hiding Implementation Details with ECMAScript 6 WeakMaps</a></li>
 <li>{{jsxref("Map")}}</li>
 <li>{{jsxref("Set")}}</li>
 <li>{{jsxref("WeakSet")}}</li>
</ul>