diff --git a/modules/33-data-types/10-primitive-data-types/index.js b/modules/33-data-types/10-primitive-data-types/index.js index ebd67389..2d111f38 100644 --- a/modules/33-data-types/10-primitive-data-types/index.js +++ b/modules/33-data-types/10-primitive-data-types/index.js @@ -1 +1,13 @@ -console.log(-0.304); +const currentYear = 2026; + +// BEGIN +const name = 'Anna'; +const birthYear = 1994; +const age = currentYear - birthYear; +const rating = 4.7; + +console.log(`Name: ${name}`); +console.log(`Birth year: ${birthYear}`); +console.log(`Age: ${age}`); +console.log(`Rating: ${rating}`); +// END diff --git a/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md b/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md index f795f618..3f05f3b6 100644 --- a/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md +++ b/modules/33-data-types/10-primitive-data-types/ru/EXERCISE.md @@ -1 +1,20 @@ -Выведите на экран число `-0.304`. +В программе уже задан текущий год: + +```javascript +const currentYear = 2026; +``` + +Напишите программу, которая выводит данные профиля в таком формате: + +```text +Name: Anna +Birth year: 1994 +Age: 32 +Rating: 4.7 +``` + +Для этого: + +- создайте переменную с годом рождения; +- вычислите возраст на основе текущего года; +- выведите данные на экран с подписями слева. diff --git a/modules/33-data-types/10-primitive-data-types/ru/README.md b/modules/33-data-types/10-primitive-data-types/ru/README.md index 65c088d9..c072f573 100644 --- a/modules/33-data-types/10-primitive-data-types/ru/README.md +++ b/modules/33-data-types/10-primitive-data-types/ru/README.md @@ -1,34 +1,75 @@ -Все значения в программировании имеют **тип**. Тип определяет, какие операции можно выполнять с данными. +Программы работают с разной информацией: текстом, числами, датами, логическими значениями. У каждого значения в программе есть тип. -## Примитивные типы в JavaScript +Например: -JavaScript имеет следующие примитивные типы: +- `'Hello, World!'` является строкой (`string`); +- `7`, `-198`, `0`, `3.14` являются числами (`number`); +- `true` и `false` являются логическими значениями (`boolean`). -| Тип | Примеры | Назначение | -|-----|---------|------------| -| `number` | `42`, `3.14`, `-7` | Числа (целые и дробные) | -| `string` | `'hello'`, `"world"` | Текст | -| `boolean` | `true`, `false` | Логические значения | -| `null` | `null` | Намеренное отсутствие значения | -| `undefined` | `undefined` | Неинициализированная переменная | +## Что такое тип данных? + +Тип данных определяет: + +- какие значения к нему относятся; +- какие операции с ним можно делать. + +Например, числа можно складывать, делить и умножать. А строки складываются по-другому — при помощи конкатенации. Умножать строку на строку бессмысленно: ```javascript -const age = 25; // number -const name = 'Alice'; // string -const isActive = true; // boolean -const nothing = null; // null -let unset; // undefined +// Бессмыслица: 'мама' * 'блокнот' ``` -## Зачем нужны типы? +## Числа и строки относятся к разным типам -Тип влияет на поведение операций. Например, `+` для чисел — это сложение, а для строк — конкатенация: +Пример вывода числа: ```javascript -console.log(1 + 2); // => 3 -console.log('1' + '2'); // => '12' +console.log(5); // => 5 +console.log(-5); // => -5 ``` +Пример вывода строки: + +```javascript +console.log('5'); // => 5 +console.log('-5'); // => -5 +``` + +На экране результат выглядит одинаково, но внутри программы это совершенно разные вещи: + +| Значение | Тип данных | +|----------|-----------------------| +| `5` | `number` (число) | +| `'5'` | `string` (строка) | + +## Числа в JavaScript + +Во многих языках целые и дробные числа — это разные типы (например, в Python это `int` и `float`). В JavaScript такого деления нет: и целые, и дробные числа относятся к одному типу — `number`. + +```javascript +console.log(10.234); // => 10.234 +console.log(-0.4); // => -0.4 + +console.log(3.5 + 1.2); // => 4.7 +console.log(5 / 2); // => 2.5 +console.log(2.75 - 0.5); // => 2.25 +``` + +## Примитивные типы + +Типы вроде `string`, `number`, `boolean` называются примитивными — они встроены прямо в язык. + +```text +Примитивные типы JavaScript +├── number : числа (целые и дробные) (7, -3, 3.14) +├── string : строки ('hello') +├── boolean : логический тип (true, false) +├── null : намеренное отсутствие значения +└── undefined : значение не задано +``` + +Кроме строк и чисел, в JavaScript есть логический тип `boolean` со значениями `true` и `false`, а также специальные значения `null` и `undefined`. Подробнее мы столкнёмся с ними в будущем. + ## Как узнать тип значения Оператор `typeof` возвращает тип в виде строки: @@ -40,3 +81,5 @@ console.log(typeof true); // => 'boolean' console.log(typeof undefined); // => 'undefined' console.log(typeof null); // => 'object' (историческая ошибка JS) ``` + +Существуют и составные типы — массивы, объекты и другие. С ними мы познакомимся позже. Более того, в JavaScript можно создавать и свои собственные типы (например, классы), но для начала важно хорошо разобраться с примитивами. diff --git a/modules/33-data-types/10-primitive-data-types/test.js b/modules/33-data-types/10-primitive-data-types/test.js index 9f88277e..dd577ec9 100644 --- a/modules/33-data-types/10-primitive-data-types/test.js +++ b/modules/33-data-types/10-primitive-data-types/test.js @@ -8,5 +8,5 @@ test('hello world', async () => { const firstArg = consoleLogSpy.mock.calls.join('\n'); - expect(firstArg).toBe('-0.304'); + expect(firstArg).toBe('Name: Anna\nBirth year: 1994\nAge: 32\nRating: 4.7'); }); diff --git a/modules/33-data-types/47-data-types-immutability/ru/README.md b/modules/33-data-types/47-data-types-immutability/ru/README.md index 0feada7b..46dee7a1 100644 --- a/modules/33-data-types/47-data-types-immutability/ru/README.md +++ b/modules/33-data-types/47-data-types-immutability/ru/README.md @@ -1,16 +1,42 @@ -**Примитивные типы** в JavaScript неизменяемы (immutable). Это значит, что после создания строку нельзя изменить — ни поменять символ, ни добавить новый. +Представим, что у нас есть строка, и мы хотим заменить в ней один символ, например первую букву имени: ```javascript let greeting = 'Hello'; - -// Попытка изменить первый символ — ничего не произойдёт greeting[0] = 'J'; console.log(greeting); // => Hello (не изменилось!) ``` -## Что можно сделать +В отличие от некоторых языков, где такая попытка приводит к ошибке, в JavaScript присваивание по индексу просто **тихо игнорируется**: строка не меняется (а в строгом режиме это вызовет ошибку `TypeError`). Причина одна: строки в JavaScript нельзя изменять по частям. После создания они становятся неизменяемыми (или, как говорят программисты, иммутабельными). + +## Почему строки неизменяемые? + +Примитивные типы (строки, числа, логические значения) в JavaScript менять нельзя. Это даёт важные преимущества: + +- Безопасность: значения не изменятся случайно. +- Производительность: с неизменяемыми значениями проще работать внутри движка. +- Предсказуемость: меньше неожиданных эффектов при передаче данных в функции. + +## А как тогда «изменить» строку? + +Если нужно «изменить» строку, создают новую на основе старой и сохраняют её в ту же переменную. Например, заменим первую букву: + +```javascript +const word = 'hello'; +const fixed = 'H' + word.slice(1); +console.log(fixed); // => Hello +``` + +```text +word = 'hello' + +word[0] = 'H' → ничего не происходит, строки неизменяемы -Переприсвоить переменную целиком — это работает: +'H' + word.slice(1) +└────────┬────────┘ + 'Hello' ← создана новая строка +``` + +Переприсвоить переменную целиком тоже можно — но это создаёт **новую** строку, а не меняет старую: ```javascript let greeting = 'Hello'; @@ -18,18 +44,22 @@ greeting = 'Jello'; console.log(greeting); // => Jello ``` -Но это создаёт **новую строку**, а не изменяет старую. - -## Зачем это знать? +## Новая переменная или та же? -Если вам нужно «изменить» строку, нужно создавать новую на основе старой. Например, заменить первый символ: +Переиспользовать переменную стоит только тогда, когда речь идёт об одной и той же сущности. Если это уже другие данные, лучше завести отдельную переменную: ```javascript -const word = 'hello'; -const fixed = 'H' + word.slice(1); -console.log(fixed); // => Hello +// Одна и та же строка, просто обновляем +let name = 'Alexander'; +name = 'Blexander'; + +// Разные сущности — лучше разные переменные +const firstName = 'Alexander'; +const correctedFirstName = 'Blexander'; ``` -## Числа тоже неизменяемы +Попытка «запихать» все строки в одну переменную запутывает код: переменная перестаёт говорить, что в ней хранится. + +## Вывод -То же самое касается чисел и булевых значений — они не объекты с изменяемым состоянием, а просто значения. +Примитивные типы данных в JavaScript (строки, числа, логические значения) являются неизменяемыми (immutable). Это означает, что после создания их значение изменить нельзя. Поменять один символ в строке невозможно — любые «изменения» происходят путём создания нового значения и переопределения переменной. diff --git a/modules/33-data-types/50-data-types-weak-typing/ru/README.md b/modules/33-data-types/50-data-types-weak-typing/ru/README.md index 04f618ed..14d6aa10 100644 --- a/modules/33-data-types/50-data-types-weak-typing/ru/README.md +++ b/modules/33-data-types/50-data-types-weak-typing/ru/README.md @@ -1,4 +1,3 @@ - Нам известно про два разных типа данных: числа и строки. Мы, например, можем складывать числа, потому что операция сложения — это операция для типа «числа». А что, если применить эту операцию не к двум числам, а к числу и строке? @@ -7,21 +6,45 @@ console.log(1 + '7'); // => 17 ``` -Несмотря на то, что `'7'` — это строка, а не число, интерпретатор JavaScript выдал ответ `17`, как если бы мы складывали две строки. Когда JavaScript видит несоответствие типов, он сам пытается преобразовать информацию. В данном случае он преобразовал число `1` в строку `'1'`, а потом спокойно сделал конкатенацию `'1'` и `'7'`. +Несмотря на то что `'7'` — это строка, а не число, интерпретатор JavaScript выдал ответ `'17'`, как если бы мы складывали две строки. Когда JavaScript видит несоответствие типов, он сам пытается преобразовать информацию. В данном случае он преобразовал число `1` в строку `'1'`, а потом спокойно сделал конкатенацию `'1'` и `'7'`. + +## Слабая типизация + +Не все языки так делают. JavaScript — это язык со **слабой типизацией**. Он знает о существовании разных типов (числа, строки и другие), но относится к их использованию не очень строго и пытается преобразовывать данные, когда это кажется ему разумным. -Не все языки так делают. JavaScript — это язык со **слабой типизацией**. Он знает о существовании разных типов (числа, строки и др.), но относится к их использованию не очень строго, пытаясь преобразовывать информацию, когда это кажется разумным. Иногда JavaScript даже доходит до крайностей. Большинство выражений, не работающих в других языках, прекрасно работают в JavaScript. Попробуйте выполнить любую арифметическую операцию (кроме сложения), подставив туда строки или любые другие типы данных (кроме ситуации, когда оба операнда - это числа или строки, содержащие только число) — вы увидите, что они всегда будут работать и возвращать `NaN`, что довольно логично. +Иногда JavaScript доходит до крайностей. Большинство выражений, которые не работают в других языках, в JavaScript отрабатывают. Попробуйте выполнить любую арифметическую операцию, кроме сложения, подставив туда строки — вы увидите, что код выполнится и вернёт `NaN` (Not a Number): ```javascript -const result = 'one' * 'two'; -console.log(result); // => NaN +console.log('one' * 'two'); // => NaN ``` -В языках со **строгой типизацией** сложить число со строкой не получится. +```text +1 + '7' → '17' (число превратилось в строку, конкатенация) +'7' - 1 → 6 (строка превратилась в число, вычитание) +'one' * 2 → NaN (строку нельзя превратить в число) +``` + +## А как в строгих языках? + +В языках со **строгой (сильной) типизацией** сложить число со строкой не получится — программа остановится с ошибкой. Например, в Python или Ruby выражение `1 + '7'` приведёт к ошибке типов: язык требует, чтобы вы явно указали, как преобразовать данные. + +При этом языки не делятся ровно на два лагеря — «строгие» и «слабые». Корректнее говорить, что у разных языков **разная степень строгости**: где-то неявных преобразований почти нет, а где-то их много. JavaScript находится у «слабого» края этой шкалы. + +## Статическая и динамическая типизация + +Есть и другое, отдельное понятие — статическая и динамическая типизация. Оно описывает, **когда** проверяются типы. JavaScript относится к динамически типизированным языкам: типы проверяются во время работы программы. В статически типизированных языках проверка обычно происходит раньше, ещё до запуска кода. + +Важно не путать две вещи: + +- статическая/динамическая типизация отвечает на вопрос «**когда** проверяются типы»; +- сильная/слабая типизация отвечает на вопрос «**что произойдёт**, если смешать разные типы без явного преобразования». + +Это независимые свойства. JavaScript — язык динамический и слабо типизированный. -JavaScript был создан для интернета, а в интернете вся информация — это строки. Даже когда вы вводите на сайте номер телефона или год рождения, на сервер эта информация поступает не как числа, а как строки. Поэтому авторы языка решили, что автоматически преобразовывать типы — правильно и удобно. +## Почему JavaScript такой -Такое автоматическое неявное преобразование типов с одной стороны и правда удобно. Но на практике это свойство языка создает множество ошибок и проблем, которые трудно найти. Код может иногда работать, а иногда не работать — в зависимости от того, «повезло» ли в конкретном случае с автоматическим преобразованием. Программист это заметит не сразу. +JavaScript был создан для интернета, а в интернете вся информация — это строки. Даже когда вы вводите на сайте номер телефона или год рождения, на сервер эти данные приходят не как числа, а как строки. Поэтому авторы языка решили, что автоматически преобразовывать типы — удобно. -В дальнейших заданиях вы будете встречаться с таким поведением не раз. Часто будет возникать вопрос «почему мой код работает не так, как я ожидаю?». +Удобство есть, но у него высокая цена. На практике неявные преобразования создают множество ошибок, которые трудно найти: код может иногда работать, а иногда нет — в зависимости от того, «повезло» ли в конкретном случае с автоматическим преобразованием. Программист замечает это не сразу. -Слабая типизация красной нитью проходит сквозь всю разработку на Javascript. +В дальнейших заданиях вы будете встречаться с таким поведением не раз. Часто будет возникать вопрос: «почему мой код работает не так, как я ожидаю?». Слабая типизация красной нитью проходит сквозь всю разработку на JavaScript. diff --git a/modules/33-data-types/55-data-types-casting/ru/README.md b/modules/33-data-types/55-data-types-casting/ru/README.md index f2e169bc..ad5d4ffa 100644 --- a/modules/33-data-types/55-data-types-casting/ru/README.md +++ b/modules/33-data-types/55-data-types-casting/ru/README.md @@ -1,38 +1,66 @@ -JavaScript автоматически преобразует типы в некоторых ситуациях (неявное преобразование). Но иногда нужно преобразовать тип **явно** — когда точно знаете, что хотите получить. +В реальных программах часто возникает ситуация, когда данные одного типа нужно превратить в другой. Это особенно актуально при обработке ввода пользователя или данных из веб-форм: там всё приходит в виде строк, даже если вы ввели число. -## Функции преобразования +JavaScript умеет преобразовывать типы автоматически (неявное преобразование), но полагаться на это опасно. Поэтому, когда вы точно знаете, какой тип хотите получить, лучше преобразовать значение **явно** — для этого есть специальные функции. + +## Преобразование строки в число + +Представим, что мы получили из формы строку `'345'`, а нам нужно сложить это число с другим: + +```javascript +const number = Number('345'); +console.log(number + 5); // => 350 +``` + +Функция `Number()` получает строку и превращает её в число. Такие функции называют функциями приведения типа (casting functions). + +```javascript +console.log(Number('0')); // => 0 +console.log(Number('10')); // => 10 +console.log(Number('3.14')); // => 3.14 +console.log(Number('hello')); // => NaN (не удалось преобразовать) +``` + +Кроме `Number()`, есть функции `parseInt()` и `parseFloat()` — они «вытягивают» из строки целое или дробное число и умеют игнорировать лишние символы в конце: ```javascript -Number('42'); // => 42 (строка → число) -Number('3.14'); // => 3.14 -Number('hello'); // => NaN (не число) +console.log(parseInt('10px')); // => 10 +console.log(parseFloat('3.5kg')); // => 3.5 +``` + +## Преобразование в строку с помощью String() -String(42); // => '42' (число → строка) -String(true); // => 'true' +Если нужно превратить число или логическое значение в строку, используйте функцию `String()`: -Boolean(0); // => false -Boolean(''); // => false -Boolean('hello'); // => true -Boolean(1); // => true +```javascript +console.log(String(10)); // => '10' +console.log(String(true)); // => 'true' +console.log(String(3.5)); // => '3.5' ``` -## Когда это нужно +Это полезно при формировании текстов и сообщений: + +```javascript +const age = 42; +console.log('Age: ' + String(age)); // => Age: 42 +// Хотя здесь удобнее интерполяция: `Age: ${age}` +``` -Чаще всего при работе с пользовательским вводом (всё приходит как строка) или при формировании текстовых сообщений из чисел. +## Преобразование в логическое значение с помощью Boolean() ```javascript -const price = 100; -const message = 'Цена: ' + String(price) + ' руб.'; -// Хотя в этом случае удобнее интерполяция: `Цена: ${price} руб.` +console.log(Boolean(0)); // => false +console.log(Boolean('')); // => false +console.log(Boolean('hello')); // => true +console.log(Boolean(1)); // => true ``` -## Math.trunc() для целой части +## Отбрасывание дробной части с помощью Math.trunc() -Чтобы отбросить дробную часть числа, используют `Math.trunc()`: +Иногда из дробного числа нужно получить целое, отбросив дробную часть. Для этого используют `Math.trunc()`: ```javascript -Math.trunc(36.6); // => 36 -Math.trunc(-36.6); // => -36 +console.log(Math.trunc(36.6)); // => 36 +console.log(Math.trunc(-36.6)); // => -36 ``` В отличие от `Math.floor()`, `Math.trunc()` просто отбрасывает дробную часть независимо от знака.