July 18, 2022

Learn JavaScript #4. Базовые операторы, математика

Урок с взаимодействием был лёгкий, понятный и по большей части знакомый, поэтому левой пяткой за 10 секунд сделал задание в две строчки и перешёл к следующему уроку. Следующий урок был с преобразованиями типов, информацию впитал, но толком не понял где это может пригодиться, поэтому конспект пропустил.

Содержание

Базовые операторы, математика

Термины: «унарный», «бинарный», «операнд»

Для начала необходимо разобраться с терминологией (мне то уж точно).

  • Операнд - то, к чему применяется оператор. Например, в умножении 5 * 2 есть два операнда: левый операнд равен 5, а правый операнд равен 2. Иногда их называют "аргументами" вместо "операндов".
  • Унарным называется оператор, который применяется к одному операнду. Например оператор унарный минус "-" меняет знак числа на противоположный.
let x = 1;

x = -x;

console.log(x); // -1, так как применили унарный минус
  • Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме:
let x = 1;
let y = 3;

console.log(y - x); // 2, так как бинарный минус вычитает значения

Формально, в последних двух примерах мы говорим о двух разных операторах, которые используют один символ "-": оператор отрицания (унарный оператор, который обращает знак) и оператор вычитания (бинарный оператор, который вычитает одно число из другого).

Математика

Поддерживаются следующие математические операторы:

  • Сложение +,
  • Вычитание -,
  • Умножение *,
  • Деление /,
  • Взятие остатка от деления %,
  • Возведение в степень **.

Первые четыре оператора очевидны, а про % и ** сейчас поговорим.

Взятие остатка %

Оператор взятия остатка %, несмотря на обозначение, никакого отношения к процентам не имеет.

Результат a % b - это остаток от целочисленного делания a на b.

Например:

console.log( 5 % 2 ); // 1, так как это остаток от деления 5 на 2
console.log( 8 % 3 ); // 2, так как это остаток от деления 8 на 3

Возведение в степень **

В выражении a ** b оператор возведения в степень умножает a на само себя b раз.

Например:

console.log( 2 ** 2); // 4 (2 во второй степени)
console.log( 2 ** 3); // 8 (2 * 2 * 2, то есть 2 в третьей степени)
console.log( 2 ** 4); // 16 (2 * 2 * 2 * 2, то есть 2 в четвёртой степени)

Математически, оператор работает и для нецелых чисел. Например квадратный корень является возведением в степень 1/2:

console.log( 4 ** (1/2) ); // 2 (степень 1/2 это взятие квадратного корня)
console.log( 8 ** (1/3) ); // 2 (степень 1/3 это взятие кубического корня)

Сложение строк при помощи бинарного +

Если хотя бы один операнд является строкой, то второй также будет преобразован в строку.

Например:

console.log( '1' + 2 ); // "12"
console.log( 2 + '1' ); // "21"

Не важно, первый или второй операнд является строкой.

Пример посложнее:

console.log( 2 + 2 + '1'); // будет "41", а не "221", так как 4 + '1' = 41

Здесь операторы работают один за другим. Первый + складывает два числа и возвращает 4, а затем следующий плюс объединяет результат со строкой производя действие 4 + '1' = '41'.

Другие арифметические операторы работают только с числами и всегда преобразуют операнды в числа.

Например вычитание и деление:

console.log( 6 - '2' ); // 4, так как '2' приводится к числу
console.log( '6' / '2'); // 3, так как оба операнда приводятся к числам

Приведение к числу, унарный +

Плюс + существует в двух формах: бинарной, которую мы использовали выше, и унарной.

Унарный, то есть применённый к одному значению, плюс + ничего не делает с числами. Но если операнд не число, унарный плюс преобразует его в число.

Например:

// Не влияет на числа
let x = 1;
console.log( +x ); // 1, никаких изменений

let y = -2;
console.log( +y ); // -2, никаких изменений

// Преобразует не числа в числа (звучит как бред, но да)
console.log( +true ); // 1
console.log( +'' ); // 0

Необходимость преобразовывать строки в числа возникает очень часто. Например, обычно значения полей HTML-формы это строки. А что, если их нужно, к примеру, сложить?

Бинарный плюс сложит их как строки:

let apples = '2';
let oranges = '3';

console.log ( apples + oranges ); // '23', бинарный плюс объединяет строки

Поэтому используем унарный плюс +, чтобы преобразовать к числу:

let apples = '2';
let oranges = '3';

// оба операнда предварительно преобразованы в числа
console.log( +apples + +oranges ); // 5, так как это уже числа, а не строки

Приоритет операторов

Существует определённый порядок выполнения операторов. Из школы мы знаем, что умножение в выражении 1 + 2 * 2 выполнится раньше сложения. Это как раз и есть приоритет.

Скобки важнее, чем приоритет, так что, если мы не удовлетворены порядком по умолчания, мы можем использовать их, чтобы изменить приоритет. Например, написать (1 + 2) * 2.

В JavaScript много операторов. Каждый оператор имеет соответствующий номер приоритета. Тот, у кого это число больше, – выполнится раньше. Если приоритет одинаковый, то порядок выполнения – слева направо.

Таблица приоритетов - нет необходимости всё запоминать.

Присваивание

В таблице приоритет есть оператор присваивания =. У него один из самых низких приоритетов: 2.

Именно поэтому, когда переменной что-либо присваивают, например, x = 2 * 2 + 1, то сначала выполнится арифметика, а затем произойдёт присваивание = с сохранением результата в x.

let x = 2 * 2 + 1

console.log( x ); // 5, как бы логично, но пусть будет

Инкремент/декремент

Одной из наиболее частых числовых операций является увеличение или уменьшение на единицу.

Для этого существуют специальные операторы:

  • Инкремент ++ увеличивает переменную на 1:
let counter = 2;
counter++; // работает как counter = counter + 1, просто запись короче
console.log( counter ); // 3, потому что 2+1=3
  • Декремент -- уменьшает переменную на 1:
let counter = 2;
counter--; // работает как counter = counter - 1, просто запись короче
console.log( counter ); // 1, потому что 2-1=1
Важно:
Инкремент/декремент можно применить только к переменной. Попытка использовать его на значении, типа 5++, приведёт к ошибке.

Побитовые операторы

Побитовые операторы работают с 32-разрядными целыми числами (при необходимости приводят к ним), на уровне их внутреннего двоичного представления.

Эти операторы не являются чем-то специфичным для JavaScript, они поддерживаются в большинстве языков программирования.

Они используются редко, когда возникает необходимости оперировать с числами на очень низком (побитовом) уровне.

Оператор «запятая»

Оператор «запятая» (,) редко применяется и является одним из самых необычных. Иногда он используется для написания более короткого кода, поэтому нам нужно знать его, чтобы понимать, что при этом происходить.

Оператор «запятая» предоставляет нам возможность вычислять несколько выражений, разделяя их запятой ,. Каждое выражение выполняется, но возвращается результат только последнего.

Например:

let a = (1 + 2, 3 + 4);

console.log( a ); // 7 (результат вычисления 3 + 4)

Первое выражение 1 + 2 выполняется, а результат отбрасывается. Затем идёт 3 + 4, выражение выполняется и возвращается результат.

Запятая имеет очень низкий приоритет

Пожалуйста, обратите внимание, что оператор , имеет очень низкий приоритет, ниже =, поэтому скобки важны в приведённом выше примере.

Без них в a = 1 + 2, 3 + 4 сначала выполнится +, суммируя числа в a = 3, 7, затем оператор присваивания = присвоит a = 3, а то, что идёт дальше, будет игнорировано. Всё так же, как в (a = 1 + 2), 3 + 4.

Но зачем нам оператор, который отбрасывает всё, кроме последнего выражения?

Иногда его используют в составе более сложных конструкций, чтобы сделать несколько действий в одной строке.

Например:

// три операции в одной строке
for (a = 1, b = 3, c = a * b; a < 10; a++) {
 ...
}

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

Задачи

Постфиксная и префиксная формы

Чему будут равны переменные a, b, c и d в примере ниже?

let a = 1, b = 1;

let c = ++a; // 2, потому что возвращает новое значение
let d = b++; // 1, потому что возвращает староезначение

// a = 2, потому что прибавилась единица
// b = 2, потому что также прибавилась единица
// c = 2, потому что c = a, а а = 2
// d = 1, потому что возвращается старое значение b = 1

Результат присваивания

Чему будут равны переменные a & x после исполнения кода в примере ниже?

let a = 2;

let x = 1 + ( a *= 2 ); 

// 5, так как a *= 2 это 2 * 2 = 4, а затем 1 + 4 = 5

Преобразование типов

Какой результат будет у выражений ниже?

"" + 1 + 0 // 10, так как при сложении 1 и 0 преобразуются в строки
"" - 1 + 0 // -1, так как при вычитании "" преобразуется к 0
true + false // 1, так как true = 1, a false = 0
6 / "3" // 2, так как "3" преобразовывается в числа
"2" * "3" // 6, так как обе строки преобразовываются в числа
4 + 5 + "px" // 9px, так как 4+5=9, а затем прибавляется строка "px"
"quot; + 4 + 5 // $45, так как при сложении 4 и 5 преобразуются в строки
"4" - 2 // 2, так как "4" преобразовывается в число
"4px" - 2 // NaN
" -9 " + 5 // " -9  5 "
" -9 " - 5 // -14, так как вычитание преобразуется к числу
null + 1 // 1, так как null = 0 после преобразовывания в число
undefined + 1 // NaN, так как undefined = NaN после преобразования
" \t \n " - 2 // -2, просто потому, что так было написано в ответах

Исправьте сложение

Ниже приведён код, который запрашивает у пользователя два числа и показывает их сумму.

Он работает неправильно. Код в примере выводит 12 (для значения полей по умолчанию)

В чём ошибка? Исправьте её. Результат должен быть 3.

let a = prompt('Первое число?', 1);
let b = prompt('Второе число?', 2);

alert( a + b ); // 12

Правильный код:

let a = prompt('', 1);
let b = prompt('', 2);

alert ( +a + +b); // 3, так как функция prompt возвращает строки и нам
// необходимо преобразовать их в числа. Далаем это с помощью приведения к
// числу при помощи бинарного +. То есть +a & +b.

// Оказывается, можно вставить бинарный + прямо перед prompt. 

Telegram-канал: unknown.dev