Чи перевіряє 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 3 рази на DOM, якщо через перше очевидно, що він поверне FALSE. (У такому випадку було б більше сенсу вкладати 3, якщо заяви).

ДОДАТОК: Більше цікавості, який правильний термін для цього? Я помічаю, що багато хто з вас використовують термін «коротке замикання». Крім того, деякі мови роблять це, а інші не роблять?


@Josh: Я повністю ціную думку, що це мікрооптимізація. Що добре знати. Якщо говорити, якщо один варіант більш оптимізований, ніж інший, я припускаю, що це добре знати і звикнути використовувати зазначений метод. (Плюс, ну, мені також було дуже цікаво щодо відповіді)
DA.

21
Строго кажучи, це не передчасна оптимізація. У мовах з логікою короткого замикання важливо знати, за яких умов деякі методи не виконуватимуться; якщо ви покладаєтесь на їх побічні ефекти, наприклад
Роб

5
Ось ще одне питання про "оцінку короткого замикання": stackoverflow.com/questions/1232603/…
Девід

@David. Дякую! Цікаве читання.
DA.

Відповіді:


151

&&Оператор «коротке замикання» - тобто, якщо ліве умова помилкова, це не заважає оцінити правильну.

Аналогічно ||коротке замикання оператора, якщо ліва умова справжня.

EDIT: Хоча, ви не повинні турбуватися про ефективність, доки не встановите орієнтир та не визначите, що це проблема. Передчасна мікрооптимізація є основою ремонту.


1
Відмінна відповідь (як технічна частина, так і питання управління). Дякую!
DA.

5
Якщо ви дійсно хочете, щоб він виконував усі частини булевої позиції, ви можете використовувати & та | для та і чи відповідно
Зойдберг

25
Ця умова не обов'язково завжди стосується продуктивності. Іноді, можливо, ви робите нульову перевірку і скажете, якщо ваша нульова перевірка є умовою a, і тоді ви намагаєтесь зробити (b == значення + 1) для другої перевірки, ви отримаєте помилку, якщо всі три умови були перевірені.
infocyde

4
Дійсно, коротке замикання не стосується продуктивності. Первісне питання, однак, задавали з точки зору ефективності.
Анон.

1
дуже добре. Проведення такого типу мікрооптимізації (серед інших) може мати великий вплив у циклі подій прокрутки, скажімо, для обчислення паралаксами декількох елементів, наприклад, або навіть липкої смуги. візьміть цей if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)приклад : друга умова - це більш дорогий розрахунок, перша - просто булева. :)
antoni

13

З точки зору продуктивності, це не мікрооптимізація.

Якщо у нас є 3 булеві змінні, a, b, c, це мікрооптимізація.

Якщо ми називаємо 3 функції, які повертають булеві змінні, кожна функція може зайняти тривалий час, і не тільки важливо знати це коротке замикання, але і в якому порядку. Наприклад:

if (takesSeconds() && takesMinutes())

набагато краще, ніж

if (takesMinutes() && takesSeconds())

якщо обидва з однаковою ймовірністю повернуть помилкове


12

Ось чому ви можете робити в JavaScript код, як

var x = x || 2;

Що означатиме, що якщо x не визначено або іншим чином 'false', то значення за замовчуванням дорівнює 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 за виправлення та зустрічний приклад


1
Ця відповідь неправильна. & і | є побітним оператором, вони НЕ 'версії короткого замикання && та ||'. Побітові оператори - це арифметичні оператори, які працюють на одиничних бітах свого операнда. Приклад: -2147483648 && 1 = 1, але -2147483648 & 1 = 0. Детальніше тут: en.wikipedia.org/wiki/Bitwise_operation
Макс

1
@Max насправді я цього не знав, я використовував це (те, що я зараз називаю "трюком"), оскільки вивчав С. На щастя, такі входи, які зламали б мій код, ніколи не з'являлися. Я виправив свою відповідь, я зобов’язаний вам
ivcandela

@DJDaveMark вибачте, що я не зміг отримати false && (alert(""))рішення про роботу: /
ivcandela

@ivcandela Ні я не міг. Якби я не був у своєму телефоні, я би перевірив це першим; o) Шкода, що ви не можете редагувати коментарі. Я тільки що видалив його і додав ще один нижче
DJDaveMark

Найпростіший і кращий спосіб примусити оцінку - зберегти результати в змінних, а потім протестувати проти змінних, тобто:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

Він перевірить усі умови лише у тому випадку, якщо перші справжні, протестуйте самі:

javascript: alert (false && alert("A") && false);

3

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


3

Ще одна причина, чому зупиняється оцінка з 1 або більше параметрами зліва.

якщо (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {...}

друге оцінювання покладається на те, що перше є істинним і не видасть помилку компіляції, якщо response.authResponse є нульовим або невизначеним і т. д., оскільки перша умова не вдалася.

Інші мови мали цю проблему в перші дні, і я думаю, що це стандартний підхід у створенні компіляторів.



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)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.