You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/10-es-modern/10-set-map/article.md
+134-6Lines changed: 134 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,9 +24,13 @@ map
24
24
// в обычном объекте это было бы одно и то же
25
25
alert( map.get(1) ); // 'num1'
26
26
alert( map.get('1') ); // 'str1'
27
+
28
+
alert( map.size ); // 3
27
29
```
28
30
29
-
Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить.
31
+
Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить. И ключи и значения сохраняются "как есть", без преобразований типов.
32
+
33
+
Свойство `map.size` хранит общее количество записей в `map`.
30
34
31
35
**При создании `Map` можно сразу инициализовать списком значений.**
Для проверки значений на эквивалентность используется алгоритм [SameValueZero](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-samevaluezero). Он аналогичен строгому равенству `===`, отличие -- в том, что `NaN` считается равным `NaN`.
69
+
70
+
Этот алгоритм жёстко фиксирован в стандарте, его нельзя изменять или задавать свою функцию для него.
65
71
[/smart]
66
72
67
-
Для удаления записей используется метод:
73
+
Для удаления записей:
68
74
<ul>
69
-
<li>`map.delete(key)` -- возвращает `true`, если ключ существовал, иначе `false`.</li>
75
+
<li>`map.delete(key)` удаляет запись с ключом `key`, возвращает `true`, если такая запись была, иначе `false`.</li>
76
+
<li>`map.clear()` -- удаляет все записи, очищает `map`.</li>
70
77
</ul>
71
78
72
79
Для проверки существования ключа:
@@ -122,6 +129,10 @@ for(let entry of recipeMap) { // то же что и recipeMap.entries()
122
129
}
123
130
```
124
131
132
+
[smart header="Перебор идёт в том же порядке, что и вставка"]
133
+
Перебор осуществляется в порядке вставки. Объекты `Map` гарантируют это, в отличие от обычных объектов `Object`.
134
+
[/smart]
135
+
125
136
Кроме того, у `Map` есть стандартный методы `forEach`, аналогичный массиву:
В примере выше многократные добавления одного и того же объекта в `set` не создают лишних копий.
150
192
193
+
Альтернатива `Set` -- это массивы с поиском дубликата при каждом добавлении, но это гораздо хуже по производительности. Или же объекты, где в качестве ключа выступает какой-нибудь уникальный идентификатор посетителя. Но это менее удобно, чем простой и наглядный `Set`.
194
+
195
+
Основные методы:
151
196
<ul>
152
-
<li>`map.size()` -- количество записей в
197
+
<li>`set.add(item)` -- добавляет в коллекцию `item`, возвращает `set` (чейнится).</li>
198
+
<li>`set.delete(item) -- удаляет `item` из коллекции, возвращает `true`, если он там был, иначе `false`.</li>
199
+
<li>`set.has(item)` -- возвращает `true`, если `item` есть в коллекции, иначе `false`.</li>
200
+
<li>`set.clear()` -- очищает `set`.</li>
201
+
</ul>
202
+
203
+
Перебор `Set` осуществляется через `forEach` или `for..of` аналогично `Map`:
204
+
205
+
```js
206
+
//+ run
207
+
'use strict';
208
+
209
+
let set =newSet(["апельсины", "яблоки", "бананы"]);
210
+
211
+
// то же, что: for(let value of set)
212
+
set.forEach((value, valueAgain, set) => {
213
+
alert(value); // апельсины, затем яблоки, затем бананы
214
+
});
215
+
```
216
+
217
+
Заметим, что в `Map` у функции в `.forEach` три аргумента: ключ, значение, объект `map`.
218
+
219
+
В `Set` для совместимости с `Map` сделано похожим образом -- у `.forEach`-функции также три аргумента. Но первые два всегда совпадают и содержат очередное значение множества.
220
+
221
+
## WeakMap и WeakSet
222
+
223
+
`WeakSet` -- особый вид `Set` не препятствующий сборщику мусора. То же самое -- `WeakMap` для `Map`.
224
+
225
+
То есть, если некий объект присутствует только в `WeakSet/WeakMap` -- он удаляется из памяти.
226
+
227
+
Это нужно для тех ситуаций, когда сами объекты используются где-то в другом месте кода, а здесь мы хотим хранить для них "вспомогательные" данные, существующие лишь пока жив объект.
228
+
229
+
Например, у нас есть элементы на странице или, к примеру, пользователи, и мы хотим хранить для них вспомогательную инфомацию, например обработчики событий или просто данные, но действительные лишь пока объект, к которому они относятся, существует.
230
+
231
+
Если поместить такие данные в `WeakMap`, а объект сделать ключом, то они будут автоматически удалены из памяти, когда удалится элемент.
232
+
233
+
Например:
234
+
```js
235
+
// текущие активные пользователи
236
+
let activeUsers = [
237
+
{name:"Вася"},
238
+
{name:"Петя"},
239
+
{name:"Маша"}
240
+
];
241
+
242
+
// вспомогательная информация о них,
243
+
// которая напрямую не входит в объект юзера,
244
+
// и потому хранится отдельно
245
+
let weakMap =newWeakMap();
246
+
247
+
weakMap[activeUsers[0]] =1;
248
+
weakMap[activeUsers[1]] =2;
249
+
weakMap[activeUsers[2]] =3;
250
+
251
+
alert( weakMap[activeUsers[0]].name ); // Вася
252
+
253
+
activeUsers.splice(0, 1); // Вася более не активный пользователь
254
+
255
+
// weakMap теперь содержит только 2 элемента
256
+
257
+
activeUsers.splice(0, 1); // Петя более не активный пользователь
0 commit comments