From e60ec041ae4639587ba4c0554e37f13da50ddc53 Mon Sep 17 00:00:00 2001 From: RedrockJS Date: Tue, 4 Mar 2025 16:47:30 +0300 Subject: [PATCH] update data types --- .../03-data-types/01-primitive-methods.md | 13 +- docs/javascript/03-data-types/02-numbers.md | 123 +++++++++++++ docs/javascript/03-data-types/03-strings.md | 95 ++++++++++ docs/javascript/03-data-types/04-arrays.md | 78 ++++++++ .../03-data-types/05-array-methods.md | 167 ++++++++++++++++++ docs/javascript/03-data-types/06-map-set.md | 97 ++++++++++ .../03-data-types/07-weakMap-weakSet.md | 63 +++++++ .../03-data-types/08-objects-methods.md | 38 ++++ .../03-data-types/09-destr-assignment.md | 119 +++++++++++++ docs/javascript/03-data-types/10-date-time.md | 71 ++++++++ 10 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 docs/javascript/03-data-types/02-numbers.md create mode 100644 docs/javascript/03-data-types/03-strings.md create mode 100644 docs/javascript/03-data-types/04-arrays.md create mode 100644 docs/javascript/03-data-types/05-array-methods.md create mode 100644 docs/javascript/03-data-types/06-map-set.md create mode 100644 docs/javascript/03-data-types/07-weakMap-weakSet.md create mode 100644 docs/javascript/03-data-types/08-objects-methods.md create mode 100644 docs/javascript/03-data-types/09-destr-assignment.md create mode 100644 docs/javascript/03-data-types/10-date-time.md diff --git a/docs/javascript/03-data-types/01-primitive-methods.md b/docs/javascript/03-data-types/01-primitive-methods.md index bb71bc8..cec18a3 100644 --- a/docs/javascript/03-data-types/01-primitive-methods.md +++ b/docs/javascript/03-data-types/01-primitive-methods.md @@ -8,10 +8,21 @@ sidebar_position: 1 #### Примитив - Это – значение «примитивного» типа. -- Есть 7 примитивных типов: string, number, boolean, symbol, null, undefined и bigint. +- Есть 7 примитивных типов: **`string`**, **`number`**, **`boolean`**, **`symbol`**, **`null`**, **`undefined`** и **`bigint`**. #### Объект - Может хранить множество значений как свойства. - Объявляется при помощи фигурных скобок \{\}, например: \{name: "Рома", age: 30\}. В JavaScript есть и другие виды объектов: например, функции тоже являются объектами. + + +## Примитив как объект +1. Примитивы остаются примитивами. Одно значение, как и хотелось. +2. Язык позволяет осуществлять доступ к методам и свойствам строк, чисел, булевых значений и символов. +3. Чтобы это работало, при таком доступе создаётся специальный «объект-обёртка», который предоставляет нужную функциональность, а после удаляется. + +Каждый примитив имеет свой собственный «объект-обёртку», которые называются: **`String`**, **`Number`**, **`Boolean`**, **`Symbol`** и **`BigInt`**. Таким образом, они имеют разный набор методов. + +💥 ***null/undefined не имеют методов*** \ +Попытка доступа к свойствам такого значения возвратит ошибку: diff --git a/docs/javascript/03-data-types/02-numbers.md b/docs/javascript/03-data-types/02-numbers.md new file mode 100644 index 0000000..a1a87be --- /dev/null +++ b/docs/javascript/03-data-types/02-numbers.md @@ -0,0 +1,123 @@ +--- +sidebar_position: 2 +--- + +# Числа +В современном JavaScript существует два типа чисел: +1. Обычные числа в JavaScript хранятся в 64-битном формате IEEE-754, который также называют «числа с плавающей точкой двойной точности» (double precision floating point numbers). +2. BigInt числа дают возможность работать с целыми числами произвольной длины. Они нужны достаточно редко и используются в случаях, когда необходимо работать со значениями более чем (253-1) или менее чем -(253-1). + +### Способы записи числа + +```js +let billion = 1000000000; +let billion = 1_000_000_000 +let billion = 1e9; +``` +```js +let mcs = 0.000001; +let ms = 1e-6; // шесть нулей слева от 1 +let a = 0b11111111; // двоичная (бинарная) форма записи числа 255 +let b = 0o377; // восьмеричная форма записи числа 255 +``` +### toString(base) +**base** может варьироваться от 2 до 36 (по умолчанию 10). +```js +alert( (255).toString(16) ); // ff +alert( (255).toString(2) ); // 11111111 +alert( 123456..toString(36) ); // 2n9c +``` +Две точки в 123456..toString(36) это не опечатка. Если нам надо вызвать метод непосредственно на числе, как toString в примере выше, то нам надо поставить две точки .. после числа. + +### Округление +- **Math.floor** \ + Округление в меньшую сторону: 3.1 становится 3, а -1.1 — -2. +- **Math.ceil** \ + Округление в большую сторону: 3.1 становится 4, а -1.1 — -1. +- **Math.round** \ + Округление до ближайшего целого: 3.1 становится 3, 3.6 — 4, а -1.1 — -1. +- **Math.trunc** (не поддерживается в Internet Explorer) \ + Производит удаление дробной части без округления: 3.1 становится 3, а -1.1 — -1. +- Метод **toFixed(n)** \ + округляет число до n знаков после запятой и возвращает строковое представление результата.\ + ``` alert( (12.34).toFixed(1) ); // "12.3" ``` + +### Неточные вычисления +Внутри JavaScript число представлено в виде 64-битного формата IEEE-754. Для хранения числа используется 64 бита: 52 из них используется для хранения цифр, 11 для хранения положения десятичной точки и один бит отведён на хранение знака. + +```js +alert( 1e500 ); // Infinity +``` +Наиболее часто встречающаяся ошибка при работе с числами в JavaScript – это потеря точности. +```js +alert( 0.1 + 0.2 ); // 0.30000000000000004 +``` +И когда мы суммируем 2 числа, их «неточности» тоже суммируются. Наиболее надёжный способ — это округлить результат используя метод toFixed(n): +```js +alert( +(0.1 + 0.2).toFixed(2) ); // 0.3 +``` + +### Проверка: isFinite и isNaN +- Infinity (и -Infinity) — особенное численное значение, которое ведёт себя в точности как математическая бесконечность ∞. +- NaN представляет ошибку. + +**isNaN(value)** преобразует значение в число и проверяет является ли оно NaN: +```js +alert( isNaN(NaN) ); // true +alert( isNaN("str") ); // true +alert( NaN === NaN ); // false +``` + +**isFinite(value)** преобразует аргумент в число и возвращает true, если оно является обычным числом, т.е. не NaN/Infinity/-Infinity +Иногда isFinite используется для проверки, содержится ли в строке число: +```js +alert( isFinite("15") ); // true +alert( isFinite("str") ); // false, потому что специальное значение: NaN +alert( isFinite(Infinity) ); // false, потому что специальное значение: Infinity + +// вернёт true всегда, кроме ситуаций, когда аргумент - Infinity/-Infinity или не число +alert( isFinite(num) ); +``` +Методы **Number.isNaN** и **Number.isFinite** – это более «строгие» версии функций isNaN и isFinite. Они не преобразуют аргумент в число, а наоборот – первым делом проверяют, является ли аргумент числом (принадлежит ли он к типу number). +Number.isNaN(value) возвращает true только в том случае, если аргумент принадлежит к типу number и является NaN. Во всех остальных случаях возвращает false. +```js +alert( Number.isNaN(NaN) ); // true +alert( Number.isNaN("str" / 2) ); // true + +// Обратите внимание на разный результат: +alert( Number.isNaN("str") ); // false, так как "str" является строкой, а не числом +alert( isNaN("str") ); // true, так как isNaN сначала преобразует строку "str" в число и в результате преобразования получает NaN +``` +Number.isFinite(value) возвращает true только в том случае, если аргумент принадлежит к типу number и не является NaN/Infinity/-Infinity. Во всех остальных случаях возвращает false. +```js +alert( Number.isFinite(123) ); // true +alert( Number.isFinite(Infinity) ); // false +alert( Number.isFinite(2 / 0) ); // false + +// Обратите внимание на разный результат: +alert( Number.isFinite("123") ); // false, так как "123" является строкой, а не числом +alert( isFinite("123") ); // true, так как isFinite сначала преобразует строку "123" в число 123 +``` +Не стоит считать Number.isNaN и Number.isFinite более «корректными» версиями функций isNaN и isFinite. Это дополняющие друг-друга инструменты для разных задач. + +💥 **Сравнение Object.is** +Существует специальный метод Object.is, который сравнивает значения примерно как ===, но более надёжен в двух особых ситуациях: + +Работает с NaN: Object.is(NaN, NaN) === true, здесь он хорош. +Значения 0 и -0 разные: Object.is(0, -0) === false, это редко используется, но технически эти значения разные. +Во всех других случаях Object.is(a, b) идентичен a === b. + +Этот способ сравнения часто используется в спецификации JavaScript. Когда внутреннему алгоритму необходимо сравнить 2 значения на предмет точного совпадения, он использует Object.is + +### parseInt и parseFloat +Для явного преобразования к числу можно использовать + или Number(). Если строка не является в точности числом, то результат будет NaN, пробелы в начале строки и в конце игнорируются. +Функция parseInt() имеет необязательный второй параметр. Он определяет систему счисления, +```js +alert( parseInt('100px') ); // 100 +alert( parseFloat('12.5em') ); // 12.5 +alert( +"100px" ); // NaN +alert( parseInt('a123') ); // NaN +``` + +### Другие математические функции +В JavaScript встроен объект **Math**, который содержит различные математические функции и константы. diff --git a/docs/javascript/03-data-types/03-strings.md b/docs/javascript/03-data-types/03-strings.md new file mode 100644 index 0000000..c8c4070 --- /dev/null +++ b/docs/javascript/03-data-types/03-strings.md @@ -0,0 +1,95 @@ +--- +sidebar_position: 3 +--- + +# Строки + +В JavaScript любые текстовые данные являются строками. +Внутренний формат для строк — всегда UTF-16, вне зависимости от кодировки страницы. + +### Кавычки + +```js +let single = 'single-quoted'; +let double = "double-quoted"; +let backticks = `backticks`; +``` + +### Спецсимволы + +| Символ | Описание | +|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| \n | Перевод строки | +| \r | В текстовых файлах Windows для перевода строки используется комбинация символов \r\n, а на других ОС это просто \n. Это так по историческим причинам, ПО под Windows обычно понимает и просто \n. | +| \\', \\", \\` | Кавычки | +| \\\ | Обратный слеш | +| \t | Знак табуляции | +| \b, \f, \v | Backspace, Form Feed и Vertical Tab — оставлены для обратной совместимости, сейчас не используются. | + +### Длина строки +💥 **length** — это числовое свойство, а не функция, добавлять скобки не нужно. + +### Доступ к символам +```js +let str = `Hello`; + +// получаем первый символ +alert( str[0] ); // H +alert( str.at(0) ); // H + +// получаем последний символ +alert( str[str.length - 1] ); // o +alert( str.at(-1) ); // o +``` +Также можно перебрать строку посимвольно, используя for..of: + +### Строки неизменяемы +Можно создать новую строку и записать её в ту же самую переменную вместо старой. + +### Поиск подстроки +**str.indexOf** - Он ищет подстроку substr в строке str, начиная с позиции pos, и возвращает позицию, на которой располагается совпадение, либо -1 при отсутствии совпадений. +```js +let str = 'Widget with id'; + +alert( str.indexOf('Widget') ); // 0, потому что подстрока 'Widget' найдена в начале +alert( str.indexOf('widget') ); // -1, совпадений нет, поиск чувствителен к регистру + +alert( str.indexOf("id") ); // 1, подстрока "id" найдена на позиции 1 (..idget with id) +``` +💥 str.lastIndexOf(substr, position) - ищет с конца строки к её началу + +**includes** - если нам необходимо проверить, есть ли совпадение, но позиция не нужна. +```js +alert( "Widget with id".includes("Widget") ); // true +alert( "Hello".includes("Bye") ); // false +``` +**startsWith, endsWith** - начинается ли, заканчивается ли строка определённой строкой +```js +alert( "Widget".startsWith("Wid") ); // true, "Wid" — начало "Widget" +alert( "Widget".endsWith("get") ); // true, "get" — окончание "Widget" +``` + +### Получение подстроки +В JavaScript есть 3 метода для получения подстроки: **substring**, **substr** и **slice** +Из двух других вариантов, slice более гибок, он поддерживает отрицательные аргументы, и его короче писать. Так что, в принципе, можно запомнить только его. +```js +str.slice(start [, end]) // возвращает часть строки от start до (не включая) end. +str.substring(start [, end]) // возвращает часть строки между start и end (не включая) end. +str.substr(start [, length]) // - возвращает часть строки от start длины length. +``` + +### Сравнение строк +строки сравниваются посимвольно в алфавитном порядке. +1. Строчные буквы больше заглавных **'a' > 'Z'** +2. Буквы, имеющие диакритические знаки, идут «не по порядку» **'Österreich' > 'Zealand'** + +#### Правильное сравнение +«Правильный» алгоритм сравнения строк сложнее, чем может показаться, так как разные языки используют разные алфавиты. +К счастью, все современные браузеры (для IE10− нужна дополнительная библиотека Intl.JS) поддерживают стандарт ECMA 402, обеспечивающий правильное сравнение строк на разных языках с учётом их правил. + +Для этого есть соответствующий метод. + +Вызов str.localeCompare(str2) возвращает число, которое показывает, какая строка больше в соответствии с правилами языка: +- Отрицательное число, если str меньше str2. +- Положительное число, если str больше str2. +- 0, если строки равны. \ No newline at end of file diff --git a/docs/javascript/03-data-types/04-arrays.md b/docs/javascript/03-data-types/04-arrays.md new file mode 100644 index 0000000..8d0dba0 --- /dev/null +++ b/docs/javascript/03-data-types/04-arrays.md @@ -0,0 +1,78 @@ +--- +sidebar_position: 4 +--- + +# Массивы +Особая структура данных, которая называется массив(Array) - это упорядоченная коллекция данных. +```js +let arr = new Array(); +let arr = []; +``` + +### Получение последних элементов при помощи «at» +```js +let fruits = ["Apple", "Orange", "Plum"]; +// то же самое, что и fruits[fruits.length-1] +alert( fruits.at(-1) ); // Plum +``` +Другими словами, arr.at(i): +- это ровно то же самое, что и arr[i], если i >= 0. +- для отрицательных значений i, он отступает от конца массива. + +### Методы pop/push, shift/unshift +- **`push`** - Добавляет элемент в конец массива +- **`pop`** - Удаляет последний элемент из массива и возвращает его +- **`shift`** - Удаляет из массива первый элемент и возвращает его +- **`unshift`** - Добавляет элемент в начало массива + +Методы **`push`** и **`unshift`** могут добавлять сразу несколько элементов + +Методы **`push`**/**`pop`** выполняются быстро, а методы **`shift`**/**`unshift`** – медленно. + +Чтобы пройтись по элементам массива: +- **for (let i=0\; i\ b) return 1; // если первое значение больше второго + if (a == b) return 0; // если равны + if (a < b) return -1; // если первое значение меньше второго +} +``` +💥 ***Функция сравнения может вернуть любое число*** +Лучше использовать стрелочные функции +```js +arr.sort( (a, b) => a - b ); +``` +Используйте localeCompare для строк + +### reverse +Метод arr.reverse меняет порядок элементов в arr на обратный и возвращает новый массив. + +### split и join +**str.split(delim)** - разбивает строку на массив по заданному разделителю delim. +**arr.join(glue)** - создаёт строку из элементов arr, вставляя glue между ними. + +### reduce/reduceRight +Функция применяется по очереди ко всем элементам массива и «переносит» свой результат на следующий вызов. +Аргументы: +- **accumulator** – результат предыдущего вызова этой функции, равен initial при первом вызове (если передан initial), +- **item** – очередной элемент массива, +- **index** – его позиция, +- **array** – сам массив. + +```js +let arr = [1, 2, 3, 4, 5]; +let result = arr.reduce((sum, current) => sum + current, 0); +alert( result ); // 15 +``` +### Array.isArray +Массивы не образуют отдельный тип данных, так как основаны на объектах, поэтому typeof не может отличить простой объект от массива. + +### Большинство методов поддерживают «thisArg» +Все методы за исключением sort(fn) +Значение параметра thisArg становится this для func. + +### Другие функции +- arr.some(fn)/arr.every(fn) проверяет массив. +- arr.fill(value, start, end) – заполняет массив повторяющимися value, начиная с индекса start до end. +- arr.copyWithin(target, start, end) – копирует свои элементы, начиная с позиции start и заканчивая end, в себя, на позицию target (перезаписывая существующие). +- arr.flat(depth)/arr.flatMap(fn) создаёт новый плоский массив из многомерного массива. \ No newline at end of file diff --git a/docs/javascript/03-data-types/06-map-set.md b/docs/javascript/03-data-types/06-map-set.md new file mode 100644 index 0000000..b9a32f2 --- /dev/null +++ b/docs/javascript/03-data-types/06-map-set.md @@ -0,0 +1,97 @@ +--- +sidebar_position: 6 +--- + +# Map и Set +Отличия от обычного объекта **`Object`**: +- Что угодно может быть ключом, в том числе и объекты. +- Есть дополнительные методы, свойство **`size`**. + +**`Set`** – коллекция уникальных значений, так называемое «множество». + +## Map +**`Map`** – это коллекция ключ/значение, как и **`Object`**. Но основное отличие в том, что **`Map`** позволяет использовать ключи любого типа. + +Методы и свойства: + +- **new Map()** – создаёт коллекцию. +- **map.set(key, value)** – записывает по ключу key значение value. +- **map.get(key)** – возвращает значение по ключу или undefined, если ключ key отсутствует. +- **map.has(key)** – возвращает true, если ключ key присутствует в коллекции, иначе false. +- **map.delete(key)** – удаляет элемент (пару «ключ/значение») по ключу key. +- **map.clear()** – очищает коллекцию от всех элементов. +- **map.size** – возвращает текущее количество элементов. + +💥 map[key] это не совсем правильный способ использования **`Map`** \ +Поэтому нам следует использовать методы map: set, get и так далее.\ +**Map может использовать объекты в качестве ключей.** + + +💥 Как объект **`Map`** сравнивает ключи \ +Чтобы сравнивать ключи, объект **Map** использует алгоритм **SameValueZero**. Это почти такое же сравнение, что и ===, с той лишь разницей, что **NaN** считается равным **NaN**. Так что **NaN** также может использоваться в качестве ключа. + +### Перебор Map +Для перебора коллекции Map есть 3 метода: +- map.keys() – возвращает итерируемый объект по ключам, +- map.values() – возвращает итерируемый объект по значениям, +- map.entries() – возвращает итерируемый объект по парам вида [ключ, значение], этот вариант используется по умолчанию в for..of. + +💥 Используется порядок вставки +В отличие от обычных объектов **`Object`**, в **`Map`** перебор происходит в том же порядке, в каком происходило добавление элементов. +Map имеет встроенный метод **`forEach`**, схожий со встроенным методом массивов **`Array`** + +### Object.entries: Map из Object +При создании Map мы можем указать массив (или другой итерируемый объект) с парами ключ-значение для инициализации +```js +// массив пар [ключ, значение] +let map = new Map([ + ['1', 'str1'], + [1, 'num1'], + [true, 'bool1'] +]); + +alert( map.get('1') ); // str1 +``` + +Если у нас уже есть обычный объект, и мы хотели бы создать Map из него, то поможет встроенный метод Object.entries(obj), который получает объект и возвращает массив пар ключ-значение для него, как раз в этом формате. +```js +let obj = { + name: "John", + age: 30 +}; + +let map = new Map(Object.entries(obj)); + +alert( map.get('name') ); // John +``` + +### Object.fromEntries: Object из Map +Мы можем использовать **`Object.fromEntries`**, чтобы получить обычный объект из **`Map`**. +```js +let map = new Map(); +map.set('banana', 1); +map.set('orange', 2); +map.set('meat', 4); + +let obj = Object.fromEntries(map.entries()); // создаём обычный объект (*) + +alert(obj.orange); // готово! obj = { banana: 1, orange: 2, meat: 4 } +``` + +## Set +Объект Set – это особый вид коллекции: «множество» значений (без ключей), где каждое значение может появляться только один раз. +Его основные методы это: +- **`new Set(iterable)`** – создаёт **`Set`**, и если в качестве аргумента был предоставлен итерируемый объект (обычно это массив), то копирует его значения в новый **`Set`**. +- **`set.add(value)`** – добавляет значение (если оно уже есть, то ничего не делает), возвращает тот же объект set. +- **`set.delete(value)`** – удаляет значение, возвращает **`true`**, если **`value`** было в множестве на момент вызова, иначе **`false`**. +- **`set.has(value)`** – возвращает **`true`**, если значение присутствует в множестве, иначе **`false`**. +- **`set.clear()`** – удаляет все имеющиеся значения. +- **`set.size`** – возвращает количество элементов в множестве. + +### Перебор объекта Set +Мы можем перебрать содержимое объекта set как с помощью метода for..of, так и используя forEach: +**`Set`** имеет те же встроенные методы, что и **`Map`**: +- **`set.values()`** – возвращает перебираемый объект для значений, +- **`set.keys()`** – то же самое, что и **`set.values()`**, присутствует для обратной совместимости с **`Map`**, +- **`set.entries()`** – возвращает перебираемый объект для пар вида [значение, значение], присутствует для обратной совместимости с **`Map`**. +- \ No newline at end of file diff --git a/docs/javascript/03-data-types/07-weakMap-weakSet.md b/docs/javascript/03-data-types/07-weakMap-weakSet.md new file mode 100644 index 0000000..41a21f1 --- /dev/null +++ b/docs/javascript/03-data-types/07-weakMap-weakSet.md @@ -0,0 +1,63 @@ +--- +sidebar_position: 7 +--- + +**`WeakMap`** – это **`Map`**-подобная коллекция, позволяющая использовать в качестве ключей только объекты, и автоматически удаляющая их вместе с соответствующими значениями, как только они становятся недостижимыми иными путями. + +**`WeakSet`** – это **`Set`**-подобная коллекция, которая хранит только объекты и удаляет их, как только они становятся недостижимыми иными путями. + +Обе этих структуры данных не поддерживают методы и свойства, работающие со всем содержимым сразу или возвращающие информацию о размере коллекции. Возможны только операции на отдельном элементе коллекции. + +**`WeakMap`** и **`WeakSet`** используются как вспомогательные структуры данных в дополнение к «основному» месту хранения объекта. Если объект удаляется из основного хранилища и нигде не используется, кроме как в качестве ключа в **`WeakMap`** или в **`WeakSet`**, то он будет удалён автоматически. + +## WeakMap +Первое его отличие от Map в том, что ключи в WeakMap должны быть объектами, а не примитивными значениями + +Теперь, если мы используем объект в качестве ключа и если больше нет ссылок на этот объект, то он будет удалён из памяти (и из объекта WeakMap) автоматически. + +WeakMap не поддерживает перебор и методы keys(), values(), entries(), так что нет способа взять все ключи или значения из неё. + +В WeakMap присутствуют только следующие методы: +- weakMap.get(key) +- weakMap.set(key, value) +- weakMap.delete(key) +- weakMap.has(key) + +К чему такие ограничения? Из-за особенностей технической реализации. Если объект станет недостижим (как объект john в примере выше), то он будет автоматически удалён сборщиком мусора. Но нет информации, в какой момент произойдёт эта очистка. +Решение о том, когда делать сборку мусора, принимает движок JavaScript. Он может посчитать необходимым как удалить объект прямо сейчас, так и отложить эту операцию, чтобы удалить большее количество объектов за раз позже. Так что технически количество элементов в коллекции WeakMap неизвестно. Движок может произвести очистку сразу или потом, или сделать это частично. По этой причине методы для доступа ко всем сразу ключам/значениям недоступны. + +В основном, WeakMap используется в качестве дополнительного хранилища данных. + +Если мы работаем с объектом, который «принадлежит» другому коду, может быть даже сторонней библиотеке, и хотим сохранить у себя какие-то данные для него, которые должны существовать лишь пока существует этот объект, то WeakMap – как раз то, что нужно. + +Мы кладём эти данные в WeakMap, используя объект как ключ, и когда сборщик мусора удалит объекты из памяти, ассоциированные с ними данные тоже автоматически исчезнут. + +## WeakSet +Коллекция WeakSet ведёт себя похоже: +- Она аналогична Set, но мы можем добавлять в WeakSet только объекты (не примитивные значения). +- Объект присутствует в множестве только до тех пор, пока доступен где-то ещё. +- Как и Set, она поддерживает add, has и delete, но не size, keys() и не является перебираемой. + +Будучи «слабой» версией оригинальной структуры данных, она тоже служит в качестве дополнительного хранилища. Но не для произвольных данных, а скорее для значений типа «да/нет». Присутствие во множестве WeakSet может что-то сказать нам об объекте. +```js +let visitedSet = new WeakSet(); + +let john = { name: "John" }; +let pete = { name: "Pete" }; +let mary = { name: "Mary" }; + +visitedSet.add(john); // John заходил к нам +visitedSet.add(pete); // потом Pete +visitedSet.add(john); // John снова + +// visitedSet сейчас содержит двух пользователей + +// проверим, заходил ли John? +alert(visitedSet.has(john)); // true + +// проверим, заходила ли Mary? +alert(visitedSet.has(mary)); // false + +john = null; +// структура данных visitedSet будет очищена автоматически (объект john будет удалён из visitedSet) +``` \ No newline at end of file diff --git a/docs/javascript/03-data-types/08-objects-methods.md b/docs/javascript/03-data-types/08-objects-methods.md new file mode 100644 index 0000000..8af8e82 --- /dev/null +++ b/docs/javascript/03-data-types/08-objects-methods.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 8 +--- + +# keys, values, entries +.keys(), .values(), .entries(). Универсальные методы, и существует общее соглашение использовать их для структур данных. Если бы мы делали собственную структуру данных, нам также следовало бы их реализовать. +Методы поддерживаются для структур: +- Map +- Set +- Array + +### Object.keys, values, entries +Для простых объектов доступны следующие методы: +- **`Object.keys(obj)`** – возвращает массив ключей. +- **`Object.values(obj)`** – возвращает массив значений. +- **`Object.entries(obj)`** – возвращает массив пар [ключ, значение]. + +Объекты являются основой всех сложных структур в JavaScript. У нас может быть объект `data`, который реализует свой собственный метод data.values(). И мы всё ещё можем применять к нему стандартный метод `Object.values(data)`. +```js +let user = { + name: "John", + age: 30 +}; +``` +- `Object.keys(user) = ["name", "age"]` +- `Object.values(user) = ["John", 30]` +- `Object.entries(user) = [ ["name","John"], ["age",30] ]` + +💥 ***Object.keys/values/entries игнорируют символьные свойства***\ +Так же, как и цикл for..in, эти методы игнорируют свойства, использующие Symbol(...) в качестве ключей. + +### Трансформации объекта +У объектов нет множества методов, которые есть в массивах, например map, filter и других. + +Если мы хотели бы их применить, то можно использовать Object.entries с последующим вызовом Object.fromEntries: +1. Вызов **`Object.entries(obj)`** возвращает массив пар ключ/значение для obj. +2. На нём вызываем методы массива, например, **`map`**. +3. Используем `Object.fromEntries(array)` на результате, чтобы преобразовать его обратно в объект. \ No newline at end of file diff --git a/docs/javascript/03-data-types/09-destr-assignment.md b/docs/javascript/03-data-types/09-destr-assignment.md new file mode 100644 index 0000000..2271c2f --- /dev/null +++ b/docs/javascript/03-data-types/09-destr-assignment.md @@ -0,0 +1,119 @@ +--- +sidebar_position: 9 +--- + +# Деструктурирующее присваивание +Деструктуризация позволяет разбивать объект или массив на переменные при присвоении. + +Полный синтаксис для объекта: +```js +let {prop : varName = defaultValue, ...rest} = object +``` +Полный синтаксис для массива: +```js +let [item1 = defaultValue, item2, ...rest] = array +``` +Можно извлекать данные из вложенных объектов и массивов, для этого левая сторона должна иметь ту же структуру, что и правая. + +### Деструктуризация массива +```js +let arr = ["Ilya", "Kantor"]; // у нас есть массив с именем и фамилией +let [firstName, surname] = arr; // деструктурирующее присваивание +``` +💥 «Деструктуризация» не означает «разрушение». + +#### Работает с любым перебираемым объектом с правой стороны +```js +let [a, b, c] = "abc"; +let [one, two, three] = new Set([1, 2, 3]); +``` +#### Присваивайте чему угодно с левой стороны +```js +let user = {}; +[user.name, user.surname] = "Ilya Kantor".split(' '); +alert(user.name, user.surname); // Ilya Kantor +``` +#### Цикл с .entries() +```js +let user = { + name: "John", + age: 30 +}; + +for (let [key, value] of Object.entries(user)) { // цикл по ключам и значениям + alert(`${key}:${value}`); // name:John, затем age:30 +} +``` +#### Трюк обмена переменных +```js +let guest = "Jane"; +let admin = "Pete"; + +[guest, admin] = [admin, guest];// Давайте поменяем местами значения: сделаем guest = "Pete", а admin = "Jane" +alert(`${guest} ${admin}`); // Pete Jane (успешно заменено!) +``` + +### Остаточные параметры «…» +```js +let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"]; +// rest это массив элементов, начиная с 3-го +alert(rest[0]); // Consul +alert(rest[1]); // of the Roman Republic +alert(rest.length); // 2 +``` + +### Значения по умолчанию +Если мы хотим, чтобы значение «по умолчанию» заменило отсутствующее, мы можем указать его с помощью = +```js +// значения по умолчанию +let [name = "Guest", surname = "Anonymous"] = ["Julius"]; + +alert(name); // Julius (из массива) +alert(surname); // Anonymous (значение по умолчанию) +``` +Значения по умолчанию могут быть гораздо более сложными выражениями или даже функциями. Они выполняются, только если значения отсутствуют. + +### Деструктуризация объекта +Деструктурирующее присваивание также работает с объектами. +```js +let options = { + title: "Menu", + width: 100, + height: 200 +}; + +// { sourceProperty: targetVariable } +let {width: w, height: h, title} = options; + +// width -> w +// height -> h +// title -> title + +alert(title); // Menu +alert(w); // 100 +alert(h); // 200 +``` + +### Остаток объекта «…» +```js +let options = { + title: "Menu", + height: 200, + width: 100 +}; + +// title = свойство с именем title +// rest = объект с остальными свойствами +let {title, ...rest} = options; + +// сейчас title="Menu", rest={height: 200, width: 100} +alert(rest.height); // 200 +alert(rest.width); // 100 +``` + +### Умные параметры функций +```js +function showMenu(title = "Untitled", width = 200, height = 100, items = []) { + // ... +} +``` diff --git a/docs/javascript/03-data-types/10-date-time.md b/docs/javascript/03-data-types/10-date-time.md new file mode 100644 index 0000000..379c0fb --- /dev/null +++ b/docs/javascript/03-data-types/10-date-time.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 10 +--- + +# Дата и время + +- Дата и время в JavaScript представлены объектом `Date`. Нельзя создать «только дату» или «только время»: объекты `Date` всегда содержат и то, и другое. +- Счёт месяцев начинается с нуля (да, январь – это нулевой месяц). +- Дни недели в `getDay()` также отсчитываются с нуля, что соответствует воскресенью. +- Объект `Date` самостоятельно корректируется при введении значений, выходящих за рамки допустимых. Это полезно для сложения/вычитания дней/месяцев/недель. +- Даты можно вычитать, и разность возвращается в миллисекундах. Так происходит, потому что при преобразовании в число объект `Date` становится таймстампом. +- Используйте `Date.now()` для быстрого получения текущего времени в формате таймстампа. + +### Создание +- **`new Date()`** Без аргументов – создать объект Date с текущими датой и временем +- **`new Date(milliseconds)`** Создать объект Date с временем, равным количеству миллисекунд (тысячная доля секунды), прошедших с 1 января 1970 года UTC+0. +- **`new Date(datestring)`** Если аргумент всего один, и это строка, то из неё «прочитывается» дата. +- **`new Date(year, month, date, hours, minutes, seconds, ms)`** Создать объект Date с заданными компонентами в местном часовом поясе. Обязательны только первые два аргумента. + +### Получение компонентов даты +- getFullYear() - Получить год (4 цифры) +- getMonth() - Получить месяц, от 0 до 11. +- getDate() - Получить день месяца, от 1 до 31, что несколько противоречит названию метода. +- getHours(), getMinutes(), getSeconds(), getMilliseconds() - Получить, соответственно, часы, минуты, секунды или миллисекунды. +- getDay() Получить определённый день недели +- getTime() Для заданной даты возвращает таймстамп – количество миллисекунд, прошедших с 1 января 1970 года UTC+0. +- getTimezoneOffset() Возвращает разницу в минутах между UTC и местным часовым поясом: + +***Все вышеперечисленные методы возвращают значения в соответствии с местным часовым поясом.*** + +### Установка компонентов даты +- setFullYear(year, [month], [date]) +- setMonth(month, [date]) +- setDate(date) +- setHours(hour, [min], [sec], [ms]) +- setMinutes(min, [sec], [ms]) +- setSeconds(sec, [ms]) +- setMilliseconds(ms) +- setTime(milliseconds) (устанавливает дату в виде целого количества миллисекунд, прошедших с 01.01.1970 UTC) + +У всех этих методов, кроме setTime(), есть UTC-вариант, например: setUTCHours(). + +### Автоисправление даты +Автоисправление – это очень полезная особенность объектов Date. Можно устанавливать компоненты даты вне обычного диапазона значений, а объект сам себя исправит. +```js +let date = new Date(2013, 0, 32); // 32 Jan 2013 ?!? +alert(date); // ...1st Feb 2013! +``` + +### Преобразование к числу, разность дат + +Если объект Date преобразовать в число, то получим таймстамп по аналогии с date.getTime() +Важный побочный эффект: даты можно вычитать, в результате получаем разность в миллисекундах. + +### Date.now() +Существует особый метод Date.now(), возвращающий текущую метку времени. + +Семантически он эквивалентен new Date().getTime(), однако метод не создаёт промежуточный объект Date. Так что этот способ работает быстрее и не нагружает сборщик мусора. + +### Разбор строки с датой +Метод Date.parse(str) считывает дату из строки. + +Формат строки должен быть следующим: YYYY-MM-DDTHH:mm:ss.sssZ, где: +- YYYY-MM-DD – это дата: год-месяц-день. +- Символ "T" используется в качестве разделителя. +- HH:mm:ss.sss – время: часы, минуты, секунды и миллисекунды. +- Необязательная часть 'Z' обозначает часовой пояс в формате +-hh:mm. Если указать просто букву Z, то получим UTC+0. + +Возможны и более короткие варианты, например, YYYY-MM-DD или YYYY-MM, или даже YYYY. + +Вызов Date.parse(str) обрабатывает строку в заданном формате и возвращает таймстамп (количество миллисекунд с 1 января 1970 года UTC+0). Если формат неправильный, возвращается NaN. \ No newline at end of file