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

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

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

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

Для тех, кто не в кур­се: что за JavaScript

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

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

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

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

Что за типы

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

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

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

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

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

2000 == ‘2000’
> Ошибка: невозможно сравнить строку с числом
> Или вернёт false, потому что строка не равна числу

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

    
language: JavaScript
if(2000 == '2000'){

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


Ско­пи­ро­вать код
Код ско­пи­ро­ван

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

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

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

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

    
language: JavaScript
let year = '2000';

//В переменной строка, а не число. Мы могли получить её от пользователя и могли загрузить из базы данных. Мы думаем, что это число 2 000, но это строка — два-ноль-ноль-ноль.

if (year>1999){

   // Мы ожидаем, что если эта часть кода выполняется, то мы работаем с годами больше 1999. И предполагаем, что это числа.

   let year2 = year+20;

   // Резонно ожидать, что в переменной year2 сейчас будет лежать 2000 + 20 = 2020 год. Но…

   console.log(year2);

}


Ско­пи­ро­вать код
Код ско­пи­ро­ван

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

Что делать

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

    
language: JavaScript
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 повсю­ду, и если вы хоти­те стать масте­ром это­го язы­ка, нуж­но пони­мать и его огра­ни­че­ния. Дер­жи­те дан­ные в чисто­те!

Ещё по теме