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
Если поместить такие данные в `WeakMap`, а объект сделать ключом, то они будут автоматически удалены из памяти, когда удалится элемент.
232
232
233
233
Например:
234
+
234
235
```js
235
236
// текущие активные пользователи
236
237
let activeUsers = [
@@ -248,7 +249,7 @@ weakMap[activeUsers[0]] = 1;
248
249
weakMap[activeUsers[1]] =2;
249
250
weakMap[activeUsers[2]] =3;
250
251
251
-
alert( weakMap[activeUsers[0]].name ); //Вася
252
+
alert( weakMap[activeUsers[0]] ); //1
252
253
253
254
activeUsers.splice(0, 1); // Вася более не активный пользователь
254
255
@@ -259,8 +260,30 @@ activeUsers.splice(0, 1); // Петя более не активный поль
259
260
// weakMap теперь содержит только 1 элемент
260
261
```
261
262
262
-
TODO WRITE MORE
263
+
У WeakMap есть ряд ограничений:
264
+
<ul>
265
+
<li>Нет свойства `size`.</li>
266
+
<li>Нельзя перебрать элементы итератором или `forEach`.</li>
267
+
<li>Нет метода `clear()`.</li>
268
+
</ul>
269
+
270
+
Иными словами, `WeakMap` работает только на запись (`set`, `delete`) и чтение (`get`, `has`) элементов по конкретному ключу, а не как полноценная коллекция. Нельзя вывести всё содержимое `WeakMap`, нет соответствующих методов.
271
+
272
+
Это связано с тем, что содержимое `WeakMap` может быть модифицировано сборщиком мусора в любой момент, независимо от программиста. Сборщик мусора работает сам по себе. Он не гарантирует, что очистит объект сразу же, когда это стало возможным. Нет какого-то конкретного момента, когда такая очистка точно произойдёт -- это определяется внутренними алгоритмами сборщика и его сведениями о системе.
273
+
274
+
Поэтому содержимое `WeakMap` в произвольный момент, строго говоря, не определено. Может быть, сборщик мусора уже удалил какие-то записи, а может и нет. С этим, а также с требованиями к эффективной реализации `WeakMap`, и связано отсутствие методов, осуществляющих доступ ко всем записям.
263
275
276
+
То же самое относится и к `WeakSet`: можно добавлять элементы, проверять их наличие, но нельзя получить их список и даже узнать количество.
277
+
278
+
Эти ограничения могут показаться неудобными, но по сути они не мешают `WeakMap/WeakSet` выполнять свою основную задачу -- быть "вторичным" хранилищем данных для объектов, актуальный список которых (и сами они) хранятся в каком-то другом месте.
279
+
280
+
## Итого
281
+
282
+
<ul>
283
+
<li>`Map` -- коллекция записей вида `ключ: значение`, лучше `Object` тем, что перебирает всегда в порядке вставки и допускает любые ключи.</li>
284
+
<li>`Set` -- коллекция уникальных элементов, также допускает любые ключи.
285
+
<li>`WeakMap` и `WeakSet` -- "урезанные" по функционалу варианты `Map/Set`, которые позволяют только "точечно" обращаться элементам (по конкретному ключу или значению). Они не препятствуют сборке мусора, то есть если ссылка на объект осталась только в `WeakSet/WeakMap` -- он будет удалён.</li>
А что, если в объекте больше значений, чем переменных? Можно ли куда-то присвоить "остаток"?
118
173
119
-
Такая возможность планируется в будущем стандарте ES-2016, и выглядеть она будет так:
174
+
Такой возможности в текущем стандарте нет. Она планируется в будущем стандарте, и выглядеть она будет аналогично массивам:
120
175
121
176
```js
122
177
//+ run
@@ -136,9 +191,7 @@ let {title, ...size} = menuOptions;
136
191
// size = { width: 100, height: 200} (остаток)
137
192
```
138
193
139
-
Ещё раз заметим, что аналогичный массивам оператор `...` ("spread") для объектов пока не стандарт.
140
-
141
-
Этот код будет работать, например, при использовании Babel со включёнными экспериментальными возможностями.
194
+
Этот код будет работать, например, при использовании Babel со включёнными экспериментальными возможностями, но ещё раз заметим, что в текущий стандарт такая возможность не вошла.
Здесь двоеточие `:` задаёт отображение свойства в переменную, а `=` задаёт значение по умолчанию (если нужно).
267
+
Здесь двоеточие `:` задаёт отображение свойства в переменную, а `=` задаёт выражение, которое будет использовано, если значение отсутствует (не указано или `undefined`).
215
268
216
-
Объявление переменной вначале не обязательно, если переменные уже есть, но без него при деструктуризации объекта может потребоваться обернуть выражение в скобки.
269
+
Объявление переменной в начале конструкции не обязательно. Можно использовать и существующие переменные. Однако при деструктуризации объекта может потребоваться обернуть выражение в скобки.
217
270
</li>
218
-
<li>Сложные объекты и массивы тоже работают, деструктуризации можно вкладывать.</li>
271
+
<li>Вложенные объекты и массивы тоже работают, деструктуризации можно вкладывать друг в друга, сохраняя ту же структуру, что и исходный объект/массив.</li>
219
272
</ul>
220
273
221
274
Как мы увидим далее, деструктуризации особенно пригодятся удобны при чтении объектных параметров функций.
Когда тело функции достаточно большое, то можно его обернуть в `{…}`:
261
+
Когда тело функции достаточно большое, то можно его обернуть в фигурные скобки `{…}`:
259
262
260
263
261
264
```js
262
265
//+ run
263
266
'use strict';
264
267
268
+
*!*
265
269
letgetTime= () => {
266
270
let date =newDate();
267
271
let hours =date.getHours();
268
272
let minutes =date.getMinutes();
269
273
return`${hours}:${minutes}`;
270
274
};
275
+
*/!*
271
276
272
277
alert( getTime() ); // текущее время
273
278
```
274
279
275
-
Заметим, что как только тело функции оборачивается в `{…}`, то оно уже автоматически ничего не возвращает. Нужно делать явный `return`, как в примере выше.
280
+
Заметим, что как только тело функции оборачивается в `{…}`, то оно уже автоматически перестаёт быть выражением. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить.
276
281
277
282
Функции-стрелки очень удобны в качестве коллбеков, например:
278
283
@@ -282,14 +287,18 @@ alert( getTime() ); // текущее время
282
287
283
288
let arr = [5, 8, 3];
284
289
290
+
*!*
285
291
let sorted =arr.sort( (a,b) => a - b );
292
+
*/!*
286
293
287
294
alert(sorted); // 3, 5, 8
288
295
```
289
296
297
+
Такая запись -- коротка и понятна.
298
+
290
299
## Функции-стрелки не имеют своего this
291
300
292
-
Внутри `this` -- тот же, что и снаружи.
301
+
Внутри функций-стрелок -- тот же`this`, что и снаружи.
293
302
294
303
Это очень удобно в обработчиках событий и коллбэках, например:
295
304
@@ -316,9 +325,9 @@ group.showList();
316
325
// Наш курс: Даша
317
326
```
318
327
319
-
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` внутри -- это`group.title`.
328
+
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` внутри -- тот же, что и во внешней функции `showList`. То есть, в данном случае --`group.title`.
320
329
321
-
Если бы была обычная функция, то была бы ошибка:
330
+
Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка:
322
331
323
332
```js
324
333
//+ run
@@ -340,9 +349,11 @@ let group = {
340
349
group.showList();
341
350
```
342
351
343
-
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`.
352
+
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`.
344
353
345
-
...Вместе с тем, отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора.
354
+
[warn header="Функции стрелки нельзя запускать с `new`"]
355
+
Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть вызывать через `new`.
356
+
[/warn]
346
357
347
358
## Функции-стрелки не имеют своего arguments
348
359
@@ -362,7 +373,7 @@ function f() {
362
373
f(1); // 1
363
374
```
364
375
365
-
Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments` берутся из внешней функции.
376
+
Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments`всегда берутся из внешней "обычной" функции.
366
377
367
378
Сохранение внешнего `this` и `arguments` удобно использовать для форвардинга вызовов и создания декораторов.
0 commit comments