Skip to content

Commit ff23414

Browse files
committed
es5
1 parent c978fe7 commit ff23414

1 file changed

Lines changed: 134 additions & 6 deletions

File tree

1-js/10-es-modern/10-set-map/article.md

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,13 @@ map
2424
// в обычном объекте это было бы одно и то же
2525
alert( map.get(1) ); // 'num1'
2626
alert( map.get('1') ); // 'str1'
27+
28+
alert( map.size ); // 3
2729
```
2830

29-
Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить.
31+
Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить. И ключи и значения сохраняются "как есть", без преобразований типов.
32+
33+
Свойство `map.size` хранит общее количество записей в `map`.
3034

3135
**При создании `Map` можно сразу инициализовать списком значений.**
3236

@@ -62,11 +66,14 @@ alert( visitsCountMap.get(user) ); // 123
6266

6367
[smart header="Как map сравнивает ключи"]
6468
Для проверки значений на эквивалентность используется алгоритм [SameValueZero](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-samevaluezero). Он аналогичен строгому равенству `===`, отличие -- в том, что `NaN` считается равным `NaN`.
69+
70+
Этот алгоритм жёстко фиксирован в стандарте, его нельзя изменять или задавать свою функцию для него.
6571
[/smart]
6672

67-
Для удаления записей используется метод:
73+
Для удаления записей:
6874
<ul>
69-
<li>`map.delete(key)` -- возвращает `true`, если ключ существовал, иначе `false`.</li>
75+
<li>`map.delete(key)` удаляет запись с ключом `key`, возвращает `true`, если такая запись была, иначе `false`.</li>
76+
<li>`map.clear()` -- удаляет все записи, очищает `map`.</li>
7077
</ul>
7178

7279
Для проверки существования ключа:
@@ -122,6 +129,10 @@ for(let entry of recipeMap) { // то же что и recipeMap.entries()
122129
}
123130
```
124131

132+
[smart header="Перебор идёт в том же порядке, что и вставка"]
133+
Перебор осуществляется в порядке вставки. Объекты `Map` гарантируют это, в отличие от обычных объектов `Object`.
134+
[/smart]
135+
125136
Кроме того, у `Map` есть стандартный методы `forEach`, аналогичный массиву:
126137

127138
```js
@@ -140,17 +151,134 @@ recipeMap.forEach( (value, key, map) => {
140151
```
141152

142153

154+
У `Map` есть и другие свой методы:
143155

156+
<ul>
157+
<li>`map.size()` -- возвращает количество записей,</li>
158+
<li>`map.clear()` -- удаляет все записи.</li>
159+
</ul>
144160

161+
## Set
145162

163+
`Set` -- коллекция для хранения множества значений, причём каждое значение может встречаться лишь один раз.
146164

165+
Например, к нам приходят посетители, и мы хотели бы сохранять всех, кто пришёл. Повторные визиты не должны приводить к дубликатам.
147166

167+
`Set` для этого отлично подходит:
168+
169+
```js
170+
//+ run
171+
'use strict';
172+
173+
let set = new Set();
174+
175+
let vasya = {name: "Вася"};
176+
let petya = {name: "Петя"};
177+
let dasha = {name: "Даша"};
178+
179+
// посещения
180+
set.add(vasya);
181+
set.add(petya);
182+
set.add(dasha);
183+
set.add(vasya);
184+
set.add(petya);
185+
186+
alert( set.size ); // 3
187+
188+
set.forEach( user => alert(user.name ) ); // Вася, Петя, Даша
189+
```
148190

149-
Есть и другие методы:
191+
В примере выше многократные добавления одного и того же объекта в `set` не создают лишних копий.
150192

193+
Альтернатива `Set` -- это массивы с поиском дубликата при каждом добавлении, но это гораздо хуже по производительности. Или же объекты, где в качестве ключа выступает какой-нибудь уникальный идентификатор посетителя. Но это менее удобно, чем простой и наглядный `Set`.
194+
195+
Основные методы:
151196
<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 = new Set(["апельсины", "яблоки", "бананы"]);
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 = new WeakMap();
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); // Петя более не активный пользователь
258+
259+
// weakMap теперь содержит только 1 элемент
260+
```
261+
262+
TODO WRITE MORE
263+
264+
265+
266+
267+
268+
269+
270+
271+
272+
273+
274+
275+
276+
277+
278+
279+
280+
281+
153282

154283

155-
ToDo
156284

0 commit comments

Comments
 (0)