Такой простой Boolean

Эта статья для студентов базового курса по javascript в HTML Academy.

У boolean — логического типа — есть только два значения: true и false. Он настолько прост, что иногда новички его не замечают. Разберёмся, как найти все булеаны и использовать их по полной.

Уберите лишние if

Рассмотрим простую задачу: если оценка меньше трёх, будем грустить, иначе не будем.

if (mark < 3) {
    sad = true;
} else {
    sad = false;
}

Думаю, вслух вы прочитаете это так: «Если mark меньше 3, запишем true в sad, иначе запишем туда false». Звучит естественно. Но что у нас в условии? Что бывает в ифах? Какое-то логическое выражение. Если оно истинно, выполняется первая ветка (sad = true), а если ложно, то вторая (sad = false). То есть, mark < 3 может быть true или false. Давайте посмотрим:

console.log(5 < 3); // false
console.log(2 < 3); // true
console.log(3 < 3); // false

Ничего удивительного. Думаю, вы ожидали этого. Выходит, если mark < 3 === true, мы записываем в переменную true. А если mark < 3 === false, мы записываем в неё false. Получается, в обоих случаях мы записываем в переменную то значение, которое возвращает mark < 3. Давайте так и запишем:

sad = mark < 3;

Одна строка вместо пяти. Если вы не уверены, что этот код делает то же, что с условием, — проверьте.

Иногда в условии вы используете не булевое выражение, а нечто, что неявно к нему приводится. Например:

// str — некоторая строка
if (str) {
    flag = true;
} else {
    flag = false;
}

Если строка не пустая, то условие истинно, иначе ложно. Если мы запишем flag = str, то flag получится не логический, а строковый. Это не то, что нужно. Тогда нужно просто явно привести строку к логическому типу:

flag = Boolean(str);

Тогда, если строка пустая, flag станет false, во всех остальных случаях — true.

Этот подход хорошо работает с элементами форм. У них есть булевые свойства типа required, disabled, checked, и их тоже можно выставлять сразу, без лишних условий:

input.required = mark < 3;
button.disabled = Boolean(input.value);
checkbox.checked = isNewUser && isActionAvailable;

Ещё по условию можно переключать классы:

if (mark < 3) {
    elem.classList.add('hidden');
} else {
    elem.classList.remove('hidden');
}

У classList есть ещё метод toggle. У него два параметра: имя класса, и логический параметр, о котором студенты забывают. Работает он так:

  • если второй параметр true, то класс добавится;
  • если false, то класс удалится.

То есть, вместо пяти строк можно снова написать одну:

elem.classList.toggle('hidden', mark < 3);

Выносите части условий в переменные

В этом коде при беглом взгляде не понятно, что происходит:

if ( (! inputText.required || inputText.value) && (! inputName.required || inputName.value)) {
  doSomething();
}

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

var isTextValid = ! inputText.required || inputText.value;
var isNameValid = ! inputName.required || inputName.value;

if (isTextValid && isNameValid) {
    doSomething();
}

или вынести проверку в функцию:

function isValid(input) {
    return ! input.required || input.value;
}

if (isValid(inputText) && isValid(inputName)) {
    doSomething();
}

Научитесь работать с логическими операторами

Разберитесь, как работают &&, || и !. У моего студента в проекте был такой код:

if (a && b) {
    doSomething();
}

if ( ! a || ! b) {
    doOtherthing();
}

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

  • если a === false и b === false, то a && b === false;
  • если a === false и b === true, то a && b === false;
  • если a === true и b === false, то a && b === false;
  • если a === true и b === true, то a && b === true.

Это можно записать в таблицу (вместо false обычно пишут 0, а вместо true — 1):

Значение
a
Значение
b
Значение
a && b
000
010
100
111
Таблица истинности для выражения a && b

Попробуем составить таблицу истинности для второго условия: ! a || ! b. Если a === false и b === false, то:

! a || ! b

! false || ! false

true || true

true

То есть если a === false и b === false, то ! a || ! b === true. Остальные случаи рассмотрим аналогично. Получится такая таблица:

Значение
a
Значение
b
Значение
! a || ! b
001
011
101
110
Таблица истинности для выражения ! a || ! b

Заметьте, у второе выражение истинно как раз в тех случаях, когда первое ложно, и наоборот. Поставим их рядом для сравнения:

Значение
a
Значение
b
Значение
a && b
Значение
! a || ! b
0001
0101
1001
1110
Таблица истинности для выражений a && b и ! a || ! b

То есть если:

a && b === false

то:

! a || ! b === true

и наоборот, если:

a && b === true

то:

! a || ! b === false

Получается, что вместо:

if (a && b) {
    doSomething();
}

if ( ! a || ! b) {
    doOtherthing();
}

можно писать:

if (a && b) {
    doSomething();
} else {
    doOtherthing();
}

Потренируйтесь вычислять логические выражения в уме.