JavaScript 4.5. Операторы и операнды (продолжение)
Давайте сегодня таки добьём тему, которую мы начали в прошлый раз. Что-то я тогда притомился и мы разобрали не всё и не до конца. Продолжим с того, что уже затронули.
Увеличение/уменьшение
Или, говоря умным языком, инкремент и декремент. Мы уже говорили об этом. Знаком «++» два плюса сразу после числовой переменной, её можно увеличить на единицу, а «--» позволят переменную уменьшить. Это мы уже знаем, но давайте на примерах разберёмся с формой записи, когда оператор записывается не после, а до переменной. Что меняется в этом случае? И сразу пример:
let a = 5;
let b = ++a; // Увеличиваем переменную a на 1 и присваиваем её значение переменной b.
alert('Переменная a = ' + a + ', а переменная b = ' + b);
a = 7;
b = a++; // Сначала присваиваем значение переменной a в переменную b, только потом увеличиваем a.
alert('Переменная a = ' + a + ', а переменная b = ' + b);
То же самое можно проделать и с оператором уменьшения, попробуйте сами.
Немного о присвоении
Мы уже разбирались с присвоением «=» значений нашим переменным, а используем так с самой первой заметки на эту тему. Но что нам делать, если в переменной (для простоты опять поговорим о числах) уже есть какое-то значение, а мы хотим умножить это значение на какое-то число. Записывать будем, конечно так:
a = 3;
a = a * 2.5;
Дело в том, что есть и краткая запись для подобного действия:
b = 4;
b *= 3; // краткая запись умножения значения переменной на какое-то число.
Очевидно, что кроме умножения – «=», можно так же складывать «+=», вычитать – «-=» и даже делить – «/=*». Удобно ли так записывать арифметические действия – решайте сами. Куда интереснее, что произойдёт, если справа от оператора будет записано не число, а выражение? В этом случае сначала выполнится выражение, стоящее справа от оператора, а потом уже произойдёт та операция, которая планировалась. Например:
a = 16;
a /=2;
alert(a);
a = 4;
a *= 2 + 3;
alert(a); // 20, как если бы мы выполнили 4 * (2 + 3)
Давайте не станем разбирать совсем уж экзотический оператор запятая – «,». Его так редко используют из-за его, на мой взгляд, неочевидности. Если всё же станет любопытно – погуглите в яндексе.
Операторы сравнения
А теперь переходим к самой интересной, на мой взгляд, части. Нам в сценариях на JavaScript постоянно будет нужно сравнивать какие-то значения между собой и на основе таких сравнений решать, как будет выполняться программа дальше. Сравнения добавляют в скрипты возможность ветвления и работают с переменными логического типа (boolean).
Мы говорили о нём, когда разбирались с примитивными типами данных в JavaScript, помните? Значения бывают истина (true) и ложь (false). Сравнивать можно, к примеру, числа. В этом случае всё просто, одно число может быть больше другого, оператор записывается как знак больше – «>». Число может быть меньше, записываем «<». Больше или равно, пишем – «>=» без пробелов. По аналогии, меньше или равно – «<=». Любопытно, как выглядит оператор, проверяющий переменные на их равенство. Помним же, что знак равенства – это оператор присваивания. Равенство проверяется двумя знаками равно подряд – «==». Обратите на это ваше внимание, новички здесь часто путаются, а затем никак не могут понять, почему не сработала их проверка. Говоря о сравнениях, мы пожалуй, не упомянули ещё об одном операторе, а именно «не равно». Когда мы собираемся сравнить значения на их неравенство друг другу, то в JavaScript записывают действие как восклицательный знак перед знаком равенства – «!=». Вообще же, восклицательный знак в проверках логических значений означает противоположное значение, мы столкнёмся с ним на практических занятиях, а покамест давайте весь этот большой абзац разберём на примерах:
alert(5 > 2); // true
alert(5 > 7); // false
alert(5 >= 5); // true
alert(3 == 3); // true
alert(5 != 7); // true
Стоит добавить, что результаты сравнений можно присваивать в переменные. В этом случае, переменная будет принимать одно из двух значений: true или false и, конечно, иметь логический тип данных.
a = 5 > 1;
alert(a); // true
Кроме того, можно сравнивать и строки или символы. В этом случае, чем дальше от начала алфавита находится та или иная буква, тем больше её вес, так как каждый алфавитный символ кодируется определённым числом – кодом. И числа эти растут вместе с буквами алфавита. Так, например, «Б» больше «А». Интересно поэкспериментировать со значениями, когда сравнивается одна и та же буква, но большая и маленькая. Так как эти символы кодируются разными числами, но и сравнение покажет, какая из них больше или меньше. Попробуйте на досуге, но самостоятельно. Вообще же, правила сравнения строк очень просты:
- Сначала сравниваются первые символы строк.
- Если первый символ первой строки больше, чем первый символ второй, то первая строка больше второй. Если символ меньше, то и вся первая строка меньше второй.
- Если первые символы равны, то таким же образом сравниваются уже вторые символы строк.
- Сравнение продолжается, пока не закончится одна из строк.
- Если обе строки заканчиваются одновременно, то они равны. Иначе, большей считается более длинная строка.
alert("лукоморье" > "лук"); // true
Дело-то не сложное, как оказывается.
Сравнение значений с разными типами
А вот тут всё уже не так просто. То есть, производить подобные сравнения можно, вот только всегда следует помнить о неявном преобразовании типов. Давайте снова на примерах разбираться:
alert("5" > 3); // true, строка "5" приводится к числу и потом сравнивается
alert(1 == true); // true, так как логическое true преобразуется в единицу
А вот явное приведение переменных к логическому типу может приводить к неочевидным результатам.
a = 0;
alert(Boolean(a)); // false
b = "0";
alert(Boolean(b)); // true (не пустая строка)
alert(a == b); // true (строка преобразуется неявно к числу и 0 == 0)
Всё дело в том, что строка, пусть даже состоящая из цифры «0» – уже не пустая строка, а непустая строка преобразуется в true. Ну а сравнения нуля как числа и строки тоже даёт true, так как строчка «0» преобразовывается к числу и затем сравниваются уже два одинаковых числа, вам следует помнить об этом и следить за подобными неявными преобразованиями типов. Если вы желаете избежать подобных приведений типов, то для сравнения на равенство или неравенство значений, следует использовать оператор строгого сравнения.
Строгое равенство выглядит уже не как два знака равенства, а аж три – «===». В этом случае сначала сравниваются типы двух значений и в предыдущем примере, где в переменную a мы поместили число нуль, а в переменной b строка «0» – строгое сравнение на равенство выдаст false:
alert(a === b); // false так как типы у переменных разные, а неявного приведения типов не будет
Имеется подобный же оператор сравнения на строгое неравенство, записывается он как «!==», вот он при сравнении предыдущих переменных выдаст true – истину.
null и undefined в сравнениях
О, это особый случай. С одной стороны, при строгом сравнении «===» эти значения остаются сами собой и ничему другому не равны, как и при нестрогом равенстве «==», а при прочих сравнениях: «>», «>=», «<» и «<=» null преобразуется в число 0, а undefined к особому значению NaN.
alert(null === undefined); // false
Отсюда, кстати, имеем некий математический казус:
alert(null > 0); // false, так как null преобразуется в 0, а нуль не больше нуля
alert(null == 0); // false, так как теперь null вообще не преобразуется и нулю не равен
alert(null >= 0); // true, так как null преобразуется в 0, а нуль больше или РАВЕН нулю
Следует ли запоминать все подобные примеры наизусть? Скорее нет, ибо всегда можно провести «натурный эксперимент» и выяснить, что там чему равно.
Друзья мои, вообще я практик и ужасно не люблю давать громадные объёмы теории, которая практикой не подкреплена. Мы уже и так познакомились с типами данных, их преобразованиями и операторами, которые позволяют нам делать с данными кучу всякого разного. Как по мне, уже пора провести практическое занятие, чтобы усвоить и как следует закрепить пройденный материал. Как вы считаете? Пишите своё мнение в комментариях.
И напоминаю, что на gitHub'е имеется репозиторий с материалами наших занятий, пользуйтесь ими.