Логические операторы

Для операций над логическими значениями в JavaScript есть || (ИЛИ), && (И) и ! (НЕ).

Хоть они и называются «логическими», но в JavaScript могут применяться к значениям любого типа и возвращают также значения любого типа.

|| (ИЛИ)

Оператор ИЛИ выглядит как двойной символ вертикальной черты:

result = a || b;

Логическое ИЛИ в классическом программировании работает следующим образом: "если хотя бы один из аргументов true, то возвращает true, иначе – false". В JavaScript, как мы увидим далее, это не совсем так, но для начала рассмотрим только логические значения.

Получается следующая «таблица результатов»:

alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false

Если значение не логического типа – то оно к нему приводится в целях вычислений. Например, число 1 будет воспринято как true, а 0 – как false:

if (1 || 0) { // сработает как if( true || false )
  alert( 'верно' );
}

Обычно оператор ИЛИ используется в if, чтобы проверить, выполняется ли хотя бы одно из условий, например:

var hour = 9;

if (hour < 10 || hour > 18) {
  alert( 'Офис до 10 или после 18 закрыт' );
}

Можно передать и больше условий:

var hour = 12,
  isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
  alert( 'Офис до 10 или после 18 или в выходной закрыт' );
}

Короткий цикл вычислений

JavaScript вычисляет несколько ИЛИ слева направо. При этом, чтобы экономить ресурсы, используется так называемый «короткий цикл вычисления».

Допустим, вычисляются несколько ИЛИ подряд: a || b || c || .... Если первый аргумент – true, то результат заведомо будет true (хотя бы одно из значений – true), и остальные значения игнорируются.

Это особенно заметно, когда выражение, переданное в качестве второго аргумента, имеет сторонний эффект – например, присваивает переменную.

При запуске примера ниже присвоение x не произойдёт:

var x;

true || (x = 1);

alert(x); // undefined, x не присвоен

…А в примере ниже первый аргумент – false, так что ИЛИ попытается вычислить второй, запустив тем самым присваивание:

var x;

false || (x = 1);

alert(x); // 1

Значение ИЛИ

|| запинается на «правде»,
&& запинается на «лжи».

Илья Канатов, участник курса JavaScript

Итак, как мы видим, оператор ИЛИ вычисляет ровно столько значений, сколько необходимо – до первого true.

При этом оператор ИЛИ возвращает то значение, на котором остановились вычисления. Причём, не преобразованное к логическому типу.

Например:

alert( 1 || 0 ); // 1
alert( true || 'неважно что' ); // true

alert( null || 1 ); // 1
alert( undefined || 0 ); // 0

Это используют, в частности, чтобы выбрать первое «истинное» значение из списка:

var undef; // переменная не присвоена, т.е. равна undefined
var zero = 0;
var emptyStr = "";
var msg = "Привет!";

var result = undef || zero || emptyStr || msg || 0;

alert( result ); // выведет "Привет!" - первое значение, которое является true

Если все значения «ложные», то || возвратит последнее из них:

alert( undefined || '' || false || 0 ); // 0

Итак, оператор || вычисляет операнды слева направо до первого «истинного» и возвращает его, а если все ложные – то последнее значение.

Иначе можно сказать, что "|| запинается на правде".

&& (И)

Оператор И пишется как два амперсанда &&:

result = a && b;

В классическом программировании И возвращает true, если оба аргумента истинны, а иначе – false:

alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false

Пример с if:

var hour = 12,
  minute = 30;

if (hour == 12 && minute == 30) {
  alert( 'Время 12:30' );
}

Как и в ИЛИ, в И допустимы любые значения:

if (1 && 0) { // вычислится как true && false
  alert( 'не сработает, т.к. условие ложно' );
}

К И применим тот же принцип «короткого цикла вычислений», но немного по-другому, чем к ИЛИ.

Если левый аргумент – false, оператор И возвращает его и заканчивает вычисления. Иначе – вычисляет и возвращает правый аргумент.

Например:

// Первый аргумент - true,
// Поэтому возвращается второй аргумент
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5

// Первый аргумент - false,
// Он и возвращается, а второй аргумент игнорируется
alert( null && 5 ); // null
alert( 0 && "не важно" ); // 0

Можно передать и несколько значений подряд, при этом возвратится первое «ложное» (на котором остановились вычисления), а если его нет – то последнее:

alert( 1 && 2 && null && 3 ); // null

alert( 1 && 2 && 3 ); // 3

Итак, оператор && вычисляет операнды слева направо до первого «ложного» и возвращает его, а если все истинные – то последнее значение.

Иначе можно сказать, что "&& запинается на лжи".

Приоритет у && больше, чем у ||

Приоритет оператора И && больше, чем ИЛИ ||, так что он выполняется раньше.

Поэтому в следующем коде сначала будет вычислено правое И: 1 && 0 = 0, а уже потом – ИЛИ.

alert( 5 || 1 && 0 ); // 5
Не используйте && вместо if

Оператор && в простых случаях можно использовать вместо if, например:

var x = 1;

(x > 0) && alert( 'Больше' );

Действие в правой части && выполнится только в том случае, если до него дойдут вычисления. То есть, alert сработает, если в левой части будет true.

Получился аналог:

var x = 1;

if (x > 0) {
  alert( 'Больше' );
}

Однако, как правило, вариант с if лучше читается и воспринимается. Он более очевиден, поэтому лучше использовать его. Это, впрочем, относится и к другим неочевидным применениям возможностей языка.

! (НЕ)

Оператор НЕ – самый простой. Он получает один аргумент. Синтаксис:

var result = !value;

Действия !:

  1. Сначала приводит аргумент к логическому типу true/false.
  2. Затем возвращает противоположное значение.

Например:

alert( !true ); // false
alert( !0 ); // true

В частности, двойное НЕ используют для преобразования значений к логическому типу:

alert( !!"строка" ); // true
alert( !!null ); // false

Задачи

важность: 5

Что выведет код ниже?

alert( null || 2 || undefined );

Ответ: 2, это первое значение, которое в логическом контексте даст true.

alert( null || 2 || undefined );
важность: 3

Что выведет код ниже?

alert( alert(1) || 2 || alert(3) );

Ответ: сначала 1, затем 2.

alert( alert(1) || 2 || alert(3) );

Вызов alert не возвращает значения, или, иначе говоря, возвращает undefined.

  1. Первый оператор ИЛИ || выполнит первый alert(1), получит undefined и пойдёт дальше, ко второму операнду.
  2. Так как второй операнд 2 является истинным, то вычисления завершатся, результатом undefined || 2 будет 2, которое будет выведено внешним alert( .... ).

Второй оператор || не будет выполнен, выполнение до alert(3) не дойдёт, поэтому 3 выведено не будет.

важность: 5

Что выведет код ниже?

alert( 1 && null && 2 );

Ответ: null, это первое ложное значение из списка.

alert( 1 && null && 2 );
важность: 3

Что выведет код ниже?

alert( alert(1) && alert(2) );

Ответ: 1, а затем undefined.

alert( alert(1) && alert(2) );

Вызов alert не возвращает значения, или, иначе говоря, возвращает undefined.

Поэтому до правого alert дело не дойдёт, вычисления закончатся на левом.

важность: 5

Что выведет код ниже?

alert( null || 2 && 3 || 4 );

Ответ: 3.

alert( null || 2 && 3 || 4 );

Приоритет оператора && выше, чем ||, поэтому он выполнится первым.

Последовательность вычислений:

null || 2 && 3 || 4
null || 3 || 4
3
важность: 3

Напишите условие if для проверки того факта, что переменная age находится между 14 и 90 включительно.

«Включительно» означает, что концы промежутка включены, то есть age может быть равна 14 или 90.

if (age >= 14 && age <= 90)
важность: 3

Напишите условие if для проверки того факта, что age НЕ находится между 14 и 90 включительно.

Сделайте два варианта условия: первый с использованием оператора НЕ !, второй – без этого оператора.

Первый вариант:

if (!(age >= 14 && age <= 90))

Второй вариант:

if (age < 14 || age > 90)
важность: 5

Какие из этих if верны, т.е. выполнятся?

Какие конкретно значения будут результатами выражений в условиях if(...)?

if (-1 || 0) alert( 'первое' );
if (-1 && 0) alert( 'второе' );
if (null || -1 && 1) alert( 'третье' );

Ответ: первое и третье выполнятся.

Детали:

// Выполнится
// Результат -1 || 0 = -1, в логическом контексте true
if (-1 || 0) alert( 'первое' );

// Не выполнится
// -1 && 0 = 0,  в логическом контексте false
if (-1 && 0) alert( 'второе' );

// Выполнится
// оператор && имеет больший приоритет, чем ||
// так что -1 && 1 выполнится раньше
// вычисления: null || -1 && 1 -> null || 1 -> 1
if (null || -1 && 1) alert( 'третье' );
Карта учебника

Комментарии

перед тем как писать…
  • Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  • Для одной строки кода используйте тег <code>, для нескольких строк кода — тег <pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
  • Если что-то непонятно в статье — пишите, что именно и с какого места.