Czy instrukcja javascript if z wieloma warunkami sprawdza je wszystkie?


100

W javascript, gdy używasz instrukcji if z wieloma warunkami do przetestowania, czy javascript testuje je wszystkie niezależnie, czy też zwolni przed przetestowaniem ich wszystkich, jeśli jest już fałszywa?

Na przykład:

 a = 1
 b = 2
 c = 1

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

Czy javascript przetestuje wszystkie 3 z tych warunków, czy też po zobaczeniu, że b nie jest równe 1, a zatem jest fałszywe, opuści instrukcję?

Pytam z punktu widzenia wydajności. Jeśli, na przykład, testuję 3 złożone selektory jQuery, wolałbym, aby jQuery nie przeszukiwał DOMu 3 razy, jeśli po pierwszym jest oczywiste, że zwróci FALSE. (W takim przypadku bardziej sensowne byłoby zagnieżdżenie 3 instrukcji if).

DODATEK: A raczej ciekawostka, jaki jest właściwy termin na to? Zauważyłem, że wielu z was używa terminu „zwarcie”. Ponadto, czy niektóre języki to robią, a inne nie?


@Josh: Całkowicie doceniam pomysł, że jest to mikro-optymalizacja. Co warto wiedzieć. To powiedziawszy, jeśli jedna opcja jest bardziej zoptymalizowana niż inna, zakładam, że dobrze jest wiedzieć i przyzwyczaić się do korzystania z tej metody. (No cóż, byłem po prostu bardzo ciekawy odpowiedzi)
DA.

21
Ściśle mówiąc, nie jest to przedwczesna optymalizacja. W językach z logiką zwarć ważne jest, aby wiedzieć, w jakich warunkach niektóre metody nie zostaną wykonane; jeśli na przykład polegasz na ich skutkach ubocznych.
Rob

5
Oto kolejne pytanie dotyczące „oceny zwarć”: stackoverflow.com/questions/1232603/…
David

@David. Dzięki! Ciekawa lektura.
DA.

Odpowiedzi:


151

&&„Zwarcie” operator - to znaczy, jeśli lewy warunek nie jest spełniony, to nie przeszkadza oceny właściwy.

Podobnie, ||operator zwiera, jeśli lewy warunek jest prawdziwy.

EDYCJA: Chociaż nie powinieneś martwić się o wydajność, dopóki nie przeprowadzisz testów porównawczych i nie stwierdzisz, że jest to problem. Przedwczesna mikro-optymalizacja jest zmorą konserwacji.


1
Doskonała odpowiedź (zarówno od strony technicznej, jak i zarządzania). dzięki!
DA.

5
Jeśli kiedykolwiek zechcesz, aby wykonywał wszystkie części instrukcji boolowskiej, możesz użyć & i | na i lub odpowiednio
Zoidberg

25
Ten warunek niekoniecznie zawsze dotyczy wydajności. Czasami możesz wykonać sprawdzenie wartości null i powiedzieć, że sprawdzenie wartości null jest warunkiem a, a następnie spróbujesz wykonać a (b == wartość + 1) przy drugim sprawdzeniu, otrzymasz błąd, jeśli wszystkie trzy warunki zostały sprawdzone.
infocyde

4
Rzeczywiście, zwarcie nie dotyczy wydajności. Pierwotne pytanie dotyczyło jednak wydajności.
Anon.

1
bardzo dobrze. Wykonywanie tego rodzaju mikrooptymalizacji (między innymi) może mieć duży wpływ na pętlę zdarzeń przewijania, powiedzmy na przykład obliczenie paralaksy wielu elementów lub nawet lepkiego paska. weźmy przykład: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)drugi warunek to bardziej kosztowne obliczenie, pierwszy to tylko wartość logiczna. :)
antoni

13

Z punktu widzenia wydajności nie jest to mikro-optymalizacja.

Jeśli mamy 3 zmienne logiczne, a, b, c to jest mikro-optymalizacja.

Jeśli wywołasz 3 funkcje, które zwracają zmienne logiczne, każda funkcja może zająć dużo czasu i nie tylko ważne jest, aby znać te zwarcia, ale także w jakiej kolejności. Na przykład:

if (takesSeconds() && takesMinutes())

jest znacznie lepszy niż

if (takesMinutes() && takesSeconds())

jeśli oba z równym prawdopodobieństwem zwrócą fałsz.


12

Dlatego możesz to zrobić w kodzie javascript, takim jak

var x = x || 2;

Co oznaczałoby, że jeśli x jest niezdefiniowane lub w inny sposób „fałszywe”, wówczas wartością domyślną jest 2.


3
Może to zadziałać, nawet jeśli JS nie obsługuje oceny zwarcia.
pswg

1
Czy jest to odpowiednik trójskładnika?
Mark Carpenter Jr

10

W przypadku, gdy ktoś się zastanawia, czy istnieje sposób na wymuszenie oceny wszystkich warunków, w niektórych przypadkach operatory bitowe &i |mogą być użyte

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

Należy ich używać bardzo ostrożnie, ponieważ operatory bitowe są operatorami arytmetycznymi, które działają na pojedynczych bitach ich operandu i nie zawsze mogą działać jako wersja „nie powodująca zwarcia” &&i||

Przykład:

-2147483648 && 1 = 1 

ale

-2147483648 & 1 = 0

Mam nadzieję, że pomoże to komuś, kto tu przybył, szukając takich informacji (jak ja) i dzięki @Max za korektę i kontrprzykład


1
Ta odpowiedź jest błędna. & i | są operatorami bitowymi, NIE są 'nie zwarciowymi wersjami && i ||'. Operatory bitowe to operatory arytmetyczne, które działają na pojedynczych bitach ich operandu. Przykład: -2147483648 && 1 = 1 ale -2147483648 & 1 = 0. Więcej informacji tutaj: en.wikipedia.org/wiki/Bitwise_operation
maks.

1
@Max właściwie tego nie wiedziałem, używam tego (to, co teraz nazywam „sztuczką”), odkąd studiowałem C. Na szczęście nigdy nie pojawiły się takie dane wejściowe, które mogłyby złamać mój kod. Poprawiłem odpowiedź, zawdzięczam
ivcandela

@DJDaveMark, przepraszam, nie udało mi się uruchomić twojego false && (alert(""))rozwiązania: /
ivcandela

@ivcandela Ani ja. Gdybym nie był przy telefonie, przetestowałbym go jako pierwszy; o) Szkoda, że ​​nie możesz edytować komentarzy. Właśnie go
usunąłem

Prostszym i lepszym sposobem wymuszenia oceny jest zapisanie wyników w zmiennych, a następnie przetestowanie ich ze zmiennymi, np .:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

Przetestuje wszystkie warunki tylko wtedy, gdy pierwsze z nich są prawdziwe, sprawdź to sam:

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


3

Kolejny powód zatrzymania oceny z 1 lub większą liczbą parametrów po lewej stronie.

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

druga ocena opiera się na tym, że pierwsza jest prawdziwa i nie zgłosi błędu kompilacji, jeśli response.authResponse ma wartość null lub undefined itp., ponieważ pierwszy warunek zawiódł.

Inne języki miały ten problem na początku i myślę, że obecnie jest to standardowe podejście w budowaniu kompilatorów.



2

Dla każdego, kto w tej kwestii jest zdezorientowany, ponieważ nie widzi zachowania zwarcia podczas używania ||w połączeniu z takim ?operatorem:

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

wygląda na to, że zasada zwarcia nie działa. Dlaczego ocenia drugi wyraz ||(prawda? 2: 3), podczas gdy pierwszy jest prawdziwy? Okazuje się, że jest to problem kolejności operacji, ponieważ powyższe jest odpowiednikiem

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

z ||ocenianym jako pierwszym i ?ocenianym jako drugim. Prawdopodobnie chcesz:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.