JavaScript для новичков: чем опасны нестрогие типы данных

JavaScript для новичков: чем опасны нестрогие типы данных

В JavaScript есть удобная штука, которая может сильно вам навредить.

Когда начинаешь изучать JavaScript, сначала чувствуешь эйфорию: очень легко работать с переменными, не нужно следить за типами, просто назвал и пользуешься. Но с великой свободой приходит великая ответственность. Если вы только начинаете пользоваться этим языком, обратите внимание на нюанс с типами данных.

JavaScript — это язык программирования, который чаще всего используется в веб-приложениях и на сайтах. Где именно:

  • в интернет-магазине, когда вы кликаете «Добавить в корзину», и счётчик товаров сразу обновляется;
  • когда вы при регистрации вводите неправильный имейл, и форма сразу подсвечивает вам, что он неверный;
  • в социальных сетях в браузере, когда новое сообщение приходит без перезагрузки страницы;
  • там же, когда вы можете перейти из личных сообщений в новости, продолжая слушать любимую музыку;
  • в любой браузерной игре;
  • когда на сайтах есть какая-то анимация;
  • когда сайт собирает данные для статистики;
  • когда посреди чтения статьи на вас бросается бесящая нападайка.


JavaScript — это язык, с помощью которого веб-страницы оживают, в них динамически подгружаются данные, появляются всплывающие окна, выпадающие элементы и миллион других вещей.

JavaScript работает во всех современных браузерах: если вы читаете эту страницу, то прямо сейчас ваш браузер выполняет какой-нибудь JavaScript. Вы можете открыть консоль и написать код на JavaScript, и он выполнится на этой странице.

Что за типы

В любом языке программирования вы встретите типы данных: числа, строки, массивы и т. д. Типы данных говорят компьютеру, как себя вести: например, на строку он выделяет одно количество памяти, а на число — другое. Числа он умеет складывать и умножать, а в строках — находить нужные буквы и слова.

Если сказать компьютеру «Запомни число 2000», он закодирует его особым образом. Это число можно будет умножать, вычитать из него, использовать как счётчик и сделать что-то две тысячи раз. Можно сказать «Увеличь на один», и компьютер без проблем выдаст 2 001. Если сказать «Уменьшай на один», у компьютера не возникнет сомнений, что нужно выдать 1 999.

А если сказать «Вот тебе строка с текстом ‘2000’», компьютер запомнит это как двойку и три нуля. Он понятия не имеет, что эти знаки означают: он просто запомнил последовательность символов. Можно попросить его посчитать, сколько в этой строке символов и сколько из них нулей. Можно попросить достать первый или последний символ строки (двойку или ноль). Можно попросить развернуть строку (0002). Можно добавить к этой строке слово «год». Но если сказать «Уменьшай на единицу», то компьютер в жизни не догадается, что от него ждут 1 999. В лучшем случае он подумает, что от него просят откусить от строки последний символ, и получится 200.

Строгие и нестрогие типы

Есть языки со строгими типами данных: чтобы использовать переменную с числом, нужно сначала объявить переменную как числовую, а потом уже что-то с ней делать. Записать букву в числовую переменную нельзя. Сложить число со строкой нельзя. Сравнить число со строкой тоже нельзя. Вот пример, который в большинстве строгих языков выдаст ошибку:

2000 == ‘2000’

> Ошибка: невозможно сравнить строку с числом

> Или вернёт false, потому что строка не равна числу

В JavaScript всё не так строго. Здесь достаточно просто начать пользоваться переменной, и язык сам определит, какого она будет типа. Если в JavaScript попытаться сложить строку и число, язык сам приведёт данные к одному типу и не выдаст ошибку. А если их сравнивать с помощью нестрогого оператора сравнения, то будет магия:

if(2000 == '2000'){
  alert('Я только что сравнил число и строку, и мне за это ничего не было!'); }

Что тут происходит: JavaScript видит, что сравниваются разные типы данных, и приводит их к чему-то одному. Приведение происходит автоматически под капотом, а вы видите только результат.

Чисто по-человечески это классно: я хотел сравнить 2 000 и 2 000, и у меня всё получилось. Зачем мне разбираться с этими типами?

В чём проблема

Если невнимательно следить за своими типами данных, то можно получить непредсказуемо работающий код. Например, у вас в переменной случайно оказалось не число, а строка, и если вы складываете её с числом, то… В общем, смотрите:

let year = '2000';
//В переменной строка, а не число. Мы могли получить её от пользователя и могли загрузить из базы данных. Мы думаем, что это число 2 000, но это строка — два-ноль-ноль-ноль.
if (year > 1999) {
  // Мы ожидаем, что если эта часть кода выполняется, то мы работаем с годами больше 1999. И предполагаем, что это числа.
  let year2 = year + 20;
  // Резонно ожидать, что в переменной year2 сейчас будет лежать 2000 + 20 = 2020 год. Но…
  console.log(year2);
}

В консоли после такого кода выведется не 2020, а ‘200020’. Почему? Потому что year была строкой и её не сложили с числом, а соединили (это называется конкатенация). Просто приклеили двадцатку к существующей строке.

Что делать

Чтобы справиться с этим разнобоем, стоит следить за типами и вручную приводить их куда надо. Особенно когда данные приходят от пользователя или из внешних источников. Вот пример:

let year = '2000';
//Допустим, мы всё ещё имеем на входе некую строку.
let parsedYear = Number(year);
//Мы попросили JavaScript явным образом привести year к числу. Теперь в этой переменной точно число. JavaScript отвечает.
if (parsedYear > 1999) {
  let year2 = parsedYear + 20;
  console.log(year2);
}
//Выдаст ожидаемый результат 2020

Вот что нам поможет:

toString(), String() — перевести в строку;

parseInt(), Number() — перевести в целое число;

parseFloat() — перевести в число с дробью.

Почему так сложно

Язык JavaScript создавался как простой язык для скриптования веб-страниц. Никто не думал, что много лет спустя он станет одним из самых распространённых языков веб-приложений. Поэтому изначальный JavaScript мог себе позволить некоторые вольности и допущения, которые были некритичны для тех условий, но резко упрощали работу. Например, приятно ведь не думать о типах данных, а просто использовать их?

Но теперь JavaScript повсюду, и если вы хотите стать мастером этого языка, нужно понимать и его ограничения. Держите данные в чистоте!

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Хранение данных в дереве. Это как вообще?
Хранение данных в дереве. Это как вообще?

Знакомство с Trie: это дерево, которое помогает работать со словарями.

medium
Стрелочные функции в JavaScript
Стрелочные функции в JavaScript

Почти как обычные функции, только стрелочные.

easy
Что такое JSON
Что такое JSON

Храним все данные на сервере и получаем их в нужный момент.

easy
Sublime Text
Почему настоящие мастера пишут всё в Sublime Text

Вообще всё.

easy
Зарплата 180 000. Что нужно уметь разработчику
Зарплата 180 000. Что нужно уметь разработчику

Кто готов платить эти деньги и за что.

easy
Что такое канбан
Что такое канбан

Самый узнаваемый атрибут айтишных команд.

easy
TypeScript — как JavaScript, но может больше
TypeScript — как JavaScript, но может больше

Способ избежать проблем JavaScript в больших проектах.

easy
Мощь алгоритмов: автоматический поиск всех возможных комбинаций
Мощь алгоритмов: автоматический поиск всех возможных комбинаций

Сдвигаем парадигму с помощью силы компьютеров

medium
Как выиграть в самой сложной игре мира
Как выиграть в самой сложной игре мира

Поручим это нейронке.

easy
Что не так с программированием в школе
Почему школьники не любят уроки программирования

Почему обучение основам программирования в школах такое ужасное и что с этим можно сделать.

easy
medium