diff --git a/1-js/10-es-modern/10-set-map/article.md b/1-js/10-es-modern/10-set-map/article.md
index c9fbbe8a..f1973f2a 100644
--- a/1-js/10-es-modern/10-set-map/article.md
+++ b/1-js/10-es-modern/10-set-map/article.md
@@ -24,9 +24,13 @@ map
// в обычном объекте это было бы одно и то же
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
+
+alert( map.size ); // 3
```
-Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить.
+Как видно из примера выше, для сохранения и чтения значений используются методы `get` и `set`, причём `set` можно чейнить. И ключи и значения сохраняются "как есть", без преобразований типов.
+
+Свойство `map.size` хранит общее количество записей в `map`.
**При создании `Map` можно сразу инициализовать списком значений.**
@@ -62,11 +66,14 @@ alert( visitsCountMap.get(user) ); // 123
[smart header="Как map сравнивает ключи"]
Для проверки значений на эквивалентность используется алгоритм [SameValueZero](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-samevaluezero). Он аналогичен строгому равенству `===`, отличие -- в том, что `NaN` считается равным `NaN`.
+
+Этот алгоритм жёстко фиксирован в стандарте, его нельзя изменять или задавать свою функцию для него.
[/smart]
-Для удаления записей используется метод:
+Для удаления записей:
-- `map.delete(key)` -- возвращает `true`, если ключ существовал, иначе `false`.
+- `map.delete(key)` удаляет запись с ключом `key`, возвращает `true`, если такая запись была, иначе `false`.
+- `map.clear()` -- удаляет все записи, очищает `map`.
Для проверки существования ключа:
@@ -122,6 +129,10 @@ for(let entry of recipeMap) { // то же что и recipeMap.entries()
}
```
+[smart header="Перебор идёт в том же порядке, что и вставка"]
+Перебор осуществляется в порядке вставки. Объекты `Map` гарантируют это, в отличие от обычных объектов `Object`.
+[/smart]
+
Кроме того, у `Map` есть стандартный методы `forEach`, аналогичный массиву:
```js
@@ -140,17 +151,134 @@ recipeMap.forEach( (value, key, map) => {
```
-
-
-
-
-
-
-Есть и другие методы:
+У `Map` есть и другие свой методы:
-- `map.size()` -- количество записей в
+
- `map.size()` -- возвращает количество записей,
+- `map.clear()` -- удаляет все записи.
+
+
+## Set
+
+`Set` -- коллекция для хранения множества значений, причём каждое значение может встречаться лишь один раз.
+
+Например, к нам приходят посетители, и мы хотели бы сохранять всех, кто пришёл. Повторные визиты не должны приводить к дубликатам.
+
+`Set` для этого отлично подходит:
+
+```js
+//+ run
+'use strict';
+
+let set = new Set();
+
+let vasya = {name: "Вася"};
+let petya = {name: "Петя"};
+let dasha = {name: "Даша"};
+
+// посещения
+set.add(vasya);
+set.add(petya);
+set.add(dasha);
+set.add(vasya);
+set.add(petya);
+
+alert( set.size ); // 3
+
+set.forEach( user => alert(user.name ) ); // Вася, Петя, Даша
+```
+
+В примере выше многократные добавления одного и того же объекта в `set` не создают лишних копий.
+
+Альтернатива `Set` -- это массивы с поиском дубликата при каждом добавлении, но это гораздо хуже по производительности. Или же объекты, где в качестве ключа выступает какой-нибудь уникальный идентификатор посетителя. Но это менее удобно, чем простой и наглядный `Set`.
+
+Основные методы:
+
+- `set.add(item)` -- добавляет в коллекцию `item`, возвращает `set` (чейнится).
+- `set.delete(item) -- удаляет `item` из коллекции, возвращает `true`, если он там был, иначе `false`.
+- `set.has(item)` -- возвращает `true`, если `item` есть в коллекции, иначе `false`.
+- `set.clear()` -- очищает `set`.
+
+
+Перебор `Set` осуществляется через `forEach` или `for..of` аналогично `Map`:
+
+```js
+//+ run
+'use strict';
+
+let set = new Set(["апельсины", "яблоки", "бананы"]);
+
+// то же, что: for(let value of set)
+set.forEach((value, valueAgain, set) => {
+ alert(value); // апельсины, затем яблоки, затем бананы
+});
+```
+
+Заметим, что в `Map` у функции в `.forEach` три аргумента: ключ, значение, объект `map`.
+
+В `Set` для совместимости с `Map` сделано похожим образом -- у `.forEach`-функции также три аргумента. Но первые два всегда совпадают и содержат очередное значение множества.
+
+## WeakMap и WeakSet
+
+`WeakSet` -- особый вид `Set` не препятствующий сборщику мусора. То же самое -- `WeakMap` для `Map`.
+
+То есть, если некий объект присутствует только в `WeakSet/WeakMap` -- он удаляется из памяти.
+
+Это нужно для тех ситуаций, когда сами объекты используются где-то в другом месте кода, а здесь мы хотим хранить для них "вспомогательные" данные, существующие лишь пока жив объект.
+
+Например, у нас есть элементы на странице или, к примеру, пользователи, и мы хотим хранить для них вспомогательную инфомацию, например обработчики событий или просто данные, но действительные лишь пока объект, к которому они относятся, существует.
+
+Если поместить такие данные в `WeakMap`, а объект сделать ключом, то они будут автоматически удалены из памяти, когда удалится элемент.
+
+Например:
+```js
+// текущие активные пользователи
+let activeUsers = [
+ {name: "Вася"},
+ {name: "Петя"},
+ {name: "Маша"}
+];
+
+// вспомогательная информация о них,
+// которая напрямую не входит в объект юзера,
+// и потому хранится отдельно
+let weakMap = new WeakMap();
+
+weakMap[activeUsers[0]] = 1;
+weakMap[activeUsers[1]] = 2;
+weakMap[activeUsers[2]] = 3;
+
+alert( weakMap[activeUsers[0]].name ); // Вася
+
+activeUsers.splice(0, 1); // Вася более не активный пользователь
+
+// weakMap теперь содержит только 2 элемента
+
+activeUsers.splice(0, 1); // Петя более не активный пользователь
+
+// weakMap теперь содержит только 1 элемент
+```
+
+TODO WRITE MORE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-ToDo