Skip to content

Commit 5bb3c58

Browse files
committed
es6
1 parent ff23414 commit 5bb3c58

7 files changed

Lines changed: 229 additions & 78 deletions

File tree

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ set.forEach((value, valueAgain, set) => {
231231
Если поместить такие данные в `WeakMap`, а объект сделать ключом, то они будут автоматически удалены из памяти, когда удалится элемент.
232232

233233
Например:
234+
234235
```js
235236
// текущие активные пользователи
236237
let activeUsers = [
@@ -248,7 +249,7 @@ weakMap[activeUsers[0]] = 1;
248249
weakMap[activeUsers[1]] = 2;
249250
weakMap[activeUsers[2]] = 3;
250251

251-
alert( weakMap[activeUsers[0]].name ); // Вася
252+
alert( weakMap[activeUsers[0]] ); // 1
252253

253254
activeUsers.splice(0, 1); // Вася более не активный пользователь
254255

@@ -259,8 +260,30 @@ activeUsers.splice(0, 1); // Петя более не активный поль
259260
// weakMap теперь содержит только 1 элемент
260261
```
261262

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`, и связано отсутствие методов, осуществляющих доступ ко всем записям.
263275

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>
286+
</ul>
264287

265288

266289

1-js/10-es-modern/3-destructuring/article.md

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ alert(lastName); // Кантор
2424
//+ run
2525
'use strict';
2626

27+
*!*
2728
let [firstName, lastName, ...rest] = "Юлий Цезарь Император Рима".split(" ");
29+
*/!*
2830

2931
alert(firstName); // Юлий
3032
alert(lastName); // Цезарь
@@ -33,6 +35,59 @@ alert(rest); // Император,Рима (массив из 2х элем
3335

3436
Значением `rest` будет массив из оставшихся элементов массива.
3537

38+
**Можно задать и значения по умолчанию, если массив почему-то оказался короче, чем ожидалось.**
39+
40+
Они задаются через знак `=`, например:
41+
42+
```js
43+
//+ run
44+
'use strict';
45+
46+
*!*
47+
let [firstName="Гость", lastName="Анонимный"] = [];
48+
*/!*
49+
50+
alert(firstName); // Гость
51+
alert(lastName); // Анонимный
52+
```
53+
54+
В качестве значений по умолчанию можно использовать не только примитивы, но и выражения, содержащие вызовы функций:
55+
56+
```js
57+
//+ run
58+
'use strict';
59+
60+
function defaultLastName() {
61+
return Date.now() + '-visitor';
62+
}
63+
64+
*!*
65+
// lastName получит значение, соответствующее текущей дате:
66+
let [firstName, lastName=defaultLastName()] = ["Вася"];
67+
*/!*
68+
69+
alert(firstName); // Вася
70+
alert(lastName); // 1436...-visitor
71+
```
72+
73+
Заметим, что вызов функции `defaultLastName` будет осуществлён только при необходимости, то есть если значения нет в массиве.
74+
75+
**Ненужные элементы массива можно отбросить, поставив лишнюю запятую:**
76+
77+
```js
78+
//+ run
79+
'use strict';
80+
81+
*!*
82+
// первый и второй элементы не нужны
83+
let [, , title] = "Юлий Цезарь Император Рима".split(" ");
84+
*/!*
85+
86+
alert(title); // Император
87+
```
88+
89+
В коде выше первый и второй элементы массива никуда не записались, они были отброшены. Как, впрочем, и все элементы после третьего.
90+
3691
## Деструктуризация объекта
3792

3893
Деструктуризация может "мгновенно" разобрать объект по переменным.
@@ -58,7 +113,7 @@ alert(`${title} ${width} ${height}`); // Меню 100 200
58113

59114
Как видно, свойства автоматически присваиваются соответствующим переменным.
60115

61-
Если хочется присвоить свойство объекта другой переменной, можно указать соответствие через двоеточие:
116+
Если хочется присвоить свойство объекта в переменную с другим именем, можно указать соответствие через двоеточие, вот так:
62117

63118
```js
64119
//+ run
@@ -79,7 +134,7 @@ alert(`${title} ${w} ${h}`); // Меню 100 200
79134

80135
В примере выше свойство `width` отправилось в переменную `w`, свойство `height` -- в переменную `h`, а `title` -- в переменную с тем же названием.
81136

82-
Если каких-то свойств в объекте нет,можно указать значение по умолчанию через знак равенства `=`, вот так;
137+
Если каких-то свойств в объекте нет, можно указать значение по умолчанию через знак равенства `=`, вот так;
83138

84139
```js
85140
//+ run
@@ -116,7 +171,7 @@ alert(`${title} ${w} ${h}`); // Меню 100 200
116171

117172
А что, если в объекте больше значений, чем переменных? Можно ли куда-то присвоить "остаток"?
118173

119-
Такая возможность планируется в будущем стандарте ES-2016, и выглядеть она будет так:
174+
Такой возможности в текущем стандарте нет. Она планируется в будущем стандарте, и выглядеть она будет аналогично массивам:
120175

121176
```js
122177
//+ run
@@ -136,9 +191,7 @@ let {title, ...size} = menuOptions;
136191
// size = { width: 100, height: 200} (остаток)
137192
```
138193

139-
Ещё раз заметим, что аналогичный массивам оператор `...` ("spread") для объектов пока не стандарт.
140-
141-
Этот код будет работать, например, при использовании Babel со включёнными экспериментальными возможностями.
194+
Этот код будет работать, например, при использовании Babel со включёнными экспериментальными возможностями, но ещё раз заметим, что в текущий стандарт такая возможность не вошла.
142195

143196
[smart header="Деструктуризация без объявления"]
144197

@@ -208,14 +261,14 @@ alert(`${title} ${width} ${height} ${item1} ${item2}`);
208261
<li>Синтаксис:
209262
```js
210263
let {prop : varName = default, ...} = object
211-
let [var1, var2, ...rest] = array
264+
let [var1=default, var2, ...rest] = array
212265
```
213266

214-
Здесь двоеточие `:` задаёт отображение свойства в переменную, а `=` задаёт значение по умолчанию (если нужно).
267+
Здесь двоеточие `:` задаёт отображение свойства в переменную, а `=` задаёт выражение, которое будет использовано, если значение отсутствует (не указано или `undefined`).
215268

216-
Объявление переменной вначале не обязательно, если переменные уже есть, но без него при деструктуризации объекта может потребоваться обернуть выражение в скобки.
269+
Объявление переменной в начале конструкции не обязательно. Можно использовать и существующие переменные. Однако при деструктуризации объекта может потребоваться обернуть выражение в скобки.
217270
</li>
218-
<li>Сложные объекты и массивы тоже работают, деструктуризации можно вкладывать.</li>
271+
<li>Вложенные объекты и массивы тоже работают, деструктуризации можно вкладывать друг в друга, сохраняя ту же структуру, что и исходный объект/массив.</li>
219272
</ul>
220273

221274
Как мы увидим далее, деструктуризации особенно пригодятся удобны при чтении объектных параметров функций.

1-js/10-es-modern/4-es-function/article.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,11 @@ showName("Юлий", "Цезарь", "Император", "Рима");
7676

7777
Оператор `` собирает "все оставшиеся" аргументы, поэтому такое объявление не имеет смысла:
7878
```js
79-
function f(arg1, ...rest, arg2) {
79+
function f(arg1, ...rest, arg2) { // arg2 после ...rest ?!
8080
// будет ошибка
8181
}
8282
```
83+
Параметр `...rest` должен быть в конце функции.
8384
[/warn]
8485

8586

@@ -231,13 +232,15 @@ let inc = x => x+1;
231232
let inc = function(x) { return x + 1; };
232233
```
233234

234-
Если аргументов несколько, они оборачиваются в скобки, например:
235+
Если аргументов несколько, то они оборачиваются в скобки, например:
235236

236237
```js
237238
//+ run
238239
'use strict';
239240

241+
*!*
240242
let sum = (a,b) => a + b;
243+
*/!*
241244

242245
alert( sum(1, 2) ); // 3
243246
```
@@ -248,31 +251,33 @@ alert( sum(1, 2) ); // 3
248251
//+ run
249252
'use strict';
250253

251-
let getTime = () =>
252-
`${new Date().getHours()} : ${new Date().getMinutes()}`;
254+
*!*
255+
let getTime = () => `${new Date().getHours()} : ${new Date().getMinutes()}`;
256+
*/!*
253257

254258
alert( getTime() ); // текущее время
255259
```
256260

257-
258-
Когда тело функции достаточно большое, то можно его обернуть в `{…}`:
261+
Когда тело функции достаточно большое, то можно его обернуть в фигурные скобки `{…}`:
259262

260263

261264
```js
262265
//+ run
263266
'use strict';
264267

268+
*!*
265269
let getTime = () => {
266270
let date = new Date();
267271
let hours = date.getHours();
268272
let minutes = date.getMinutes();
269273
return `${hours}:${minutes}`;
270274
};
275+
*/!*
271276

272277
alert( getTime() ); // текущее время
273278
```
274279

275-
Заметим, что как только тело функции оборачивается в `{…}`, то оно уже автоматически ничего не возвращает. Нужно делать явный `return`, как в примере выше.
280+
Заметим, что как только тело функции оборачивается в `{…}`, то оно уже автоматически перестаёт быть выражением. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить.
276281

277282
Функции-стрелки очень удобны в качестве коллбеков, например:
278283

@@ -282,14 +287,18 @@ alert( getTime() ); // текущее время
282287

283288
let arr = [5, 8, 3];
284289

290+
*!*
285291
let sorted = arr.sort( (a,b) => a - b );
292+
*/!*
286293

287294
alert(sorted); // 3, 5, 8
288295
```
289296

297+
Такая запись -- коротка и понятна.
298+
290299
## Функции-стрелки не имеют своего this
291300

292-
Внутри `this` -- тот же, что и снаружи.
301+
Внутри функций-стрелок -- тот же `this`, что и снаружи.
293302

294303
Это очень удобно в обработчиках событий и коллбэках, например:
295304

@@ -316,9 +325,9 @@ group.showList();
316325
// Наш курс: Даша
317326
```
318327

319-
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` внутри -- это `group.title`.
328+
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` внутри -- тот же, что и во внешней функции `showList`. То есть, в данном случае -- `group.title`.
320329

321-
Если бы была обычная функция, то была бы ошибка:
330+
Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка:
322331

323332
```js
324333
//+ run
@@ -340,9 +349,11 @@ let group = {
340349
group.showList();
341350
```
342351

343-
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`.
352+
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`.
344353

345-
...Вместе с тем, отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора.
354+
[warn header="Функции стрелки нельзя запускать с `new`"]
355+
Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть вызывать через `new`.
356+
[/warn]
346357

347358
## Функции-стрелки не имеют своего arguments
348359

@@ -362,7 +373,7 @@ function f() {
362373
f(1); // 1
363374
```
364375

365-
Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments` берутся из внешней функции.
376+
Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments` всегда берутся из внешней "обычной" функции.
366377

367378
Сохранение внешнего `this` и `arguments` удобно использовать для форвардинга вызовов и создания декораторов.
368379

0 commit comments

Comments
 (0)