Проверяет ли оператор if в javascript с несколькими условиями их все?

100

В javascript, при использовании оператора if с несколькими условиями для проверки, проверяет ли javascript их все независимо, или он откажется от проверки их всех, если он уже ложен?

Например:

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

Будет ли javascript проверять все 3 из этих условий или, увидев, что b не равно 1 и, следовательно, ложно, выйдет ли он из оператора?

Я спрашиваю с точки зрения производительности. Если, например, я тестирую 3 сложных селектора jQuery, я бы предпочел, чтобы jQuery не пересекал DOM 3 раза, если по первому из них очевидно, что он вернет FALSE. (В этом случае имеет смысл вложить 3 оператора if).

ДОБАВЛЕНИЕ: Скорее любопытство, как правильно это обозначить? Я заметил, что многие из вас используют термин «короткое замыкание». Кроме того, некоторые языки делают это, а другие - нет?

DA.
источник
@Josh: Я полностью понимаю, что это микрооптимизация. Что полезно знать. Тем не менее, если один вариант более оптимизирован, чем другой, я полагаю, что полезно знать и иметь привычку использовать этот метод. (Плюс, ну, мне просто было очень любопытно ответить)
DA.
21
Строго говоря, это не преждевременная оптимизация. В языках с логикой короткого замыкания важно знать, при каких условиях некоторые методы не будут выполняться; если, например, вы полагаетесь на их побочные эффекты.
Роб
5
Вот еще один вопрос об «оценке короткого замыкания»: stackoverflow.com/questions/1232603/…
Дэвид
@ Дэвид. Спасибо! Интересное чтение.
Д.А.

Ответы:

151

&&Оператор «короткое замыкание» - то есть, если левое условие ложно, это не мешает оценить правильную.

Точно так же ||оператор замыкается, если левое условие истинно.

РЕДАКТИРОВАТЬ: Тем не менее, вам не следует беспокоиться о производительности, пока вы не проведете сравнительный анализ и не определите, что это проблема. Преждевременная микрооптимизация - это проклятие ремонтопригодности.

Анон.
источник
1
Отличный ответ (как техническая часть, так и вопрос управления). Спасибо!
Д.А.
5
Если вы когда-нибудь захотите, чтобы он выполнял все части логического состояния, вы можете использовать & и | для и и или соответственно
Зойдберг
25
Это условие не всегда связано с производительностью. Иногда вы можете выполнить нулевую проверку и сказать, если ваша нулевая проверка является условием а, а затем вы попытаетесь выполнить (b == значение + 1) для своей второй проверки, вы получите сообщение об ошибке, если все три условия были проверены.
infocyde
4
В самом деле, короткое замыкание - это не производительность. Первоначальный вопрос, однако, задавался с точки зрения производительности.
Аноним.
1
очень хорошо. Выполнение такого рода микрооптимизации (среди прочего) может иметь большое влияние внутри цикла событий прокрутки, например, для вычисления параллакса нескольких элементов или даже липкой полосы. возьмем этот if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)пример : второе условие - более затратный расчет, первое - просто логическое. :)
Антони
13

С точки зрения производительности это не микрооптимизация.

Если у нас есть 3 логических переменных, a, b, c, это микрооптимизация.

Если мы вызовем 3 функции, которые возвращают логические переменные, каждая функция может занять много времени, и важно не только знать, как это происходит, но и в каком порядке. Например:

if (takesSeconds() && takesMinutes())

намного лучше чем

if (takesMinutes() && takesSeconds())

если оба с одинаковой вероятностью вернут false.

Брэд
источник
12

Вот почему вы можете сделать в коде javascript, например

var x = x || 2;

Это означало бы, что если x не определено или иначе «ложно», то значение по умолчанию равно 2.

азазул
источник
3
Это могло работать, даже если JS не поддерживал оценку короткого замыкания.
pswg
1
Это эквивалент троичной системы?
Марк Карпентер младший
10

Если кому-то интересно, есть ли способ принудительно оценить все условия, в некоторых случаях можно использовать побитовые операторы &и|

var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up

Их следует использовать очень осторожно, потому что побитовые операторы - это арифметические операторы, которые работают с отдельными битами своего операнда и не всегда могут работать как "не короткозамкнутые" версии &&и||

Пример:

-2147483648 && 1 = 1 

но

-2147483648 & 1 = 0

Надеюсь, это поможет кому-то, кто прибыл сюда в поисках такой информации (например, я), и спасибо @Max за исправление и контрпример.

ivcandela
источник
1
Это неверный ответ. & и | являются побитовыми операторами, они НЕ являются «короткозамкнутыми» версиями && и ||. Побитовые операторы - это арифметические операторы, которые работают с отдельными битами своего операнда. Пример: -2147483648 && 1 = 1, но -2147483648 & 1 = 0. Подробнее здесь: en.wikipedia.org/wiki/Bitwise_operation
Макс,
1
@Max на самом деле я этого не знал, я использовал это (то, что я теперь называю "трюком"), так как изучал C. К счастью, такие входы, которые сломали бы мой код, никогда не появлялись. Я исправил свой ответ, я тебе должен
ivcandela
@DJDaveMark, извините, я не могу заставить ваше false && (alert(""))решение работать: /
ivcandela
@ivcandela Я тоже. Если бы меня не было на телефоне, я бы сначала протестировал его; o) Жаль, что вы не можете редактировать комментарии. Я просто удалил его и добавил ниже
DJDaveMark 03
Более простой и лучший способ принудительно выполнить оценку - сохранить результаты в переменных, а затем протестировать их против переменных, например:var a=false; var b=check(); alert(a && b);
DJDaveMark
7

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

javascript: alert (false && alert("A") && false);
Альбертейн
источник
3

Это короткое замыкание - в вашем примере будут сравниваться только a и b.

Дэвид М
источник
3

Еще одна причина, по которой останавливается оценка с одним или несколькими параметрами слева.

if (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {...}

вторая оценка полагается на истинность первого и не выдаст ошибку компиляции, если response.authResponse имеет значение null или undefined и т.д., потому что первое условие не выполнено.

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

PazoozaTest Pazman
источник
2

Он выходит после того, как увидит, что b не равно единице.

Энни
источник
2

Для всех, кто задается этим вопросом в замешательстве, потому что они не видят поведения короткого замыкания при использовании ||в сочетании с таким ?оператором:

x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

похоже, что правило короткого замыкания не работает. Почему он оценивает второй член ||(верно? 2: 3), когда первое верно? Оказывается, это проблема порядка операций, потому что приведенное выше эквивалентно

x = (1 || true) ? 2 : 3

с ||оцениваемым первым и ?оцениваемым вторым. Скорее всего, вы захотите:

x = 1 || (true ? 2 : 3)

Яркоглазый
источник