Pytanie Czy instrukcja javascript if z wieloma warunkami testuje je wszystkie?


W javascript, gdy używasz instrukcji if z wieloma warunkami do przetestowania, czy javascript przetestuje je wszystkie bez względu na to, czy też wypłaci je przed testowaniem wszystkich, jeśli jest już fałszywy?

Na przykład:

 a = 1
 b = 2
 c = 1

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

Czy test javascript dla wszystkich 3 z tych warunków, czy po zobaczeniu, że b nie jest równy 1, a zatem jest fałszywy, czy wyjdzie z tego oświadczenia?

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

ADDENDUM: Więcej ciekawości, jaki jest właściwy termin na to? Zauważam, że wielu z was używa terminu "zwarcie". Czy niektóre języki robią to, a inne nie?


76
2017-12-18 20:26


pochodzenie


@ Jos: Całkowicie doceniam pomysł, że jest to mikrooptymalizacja. Co warto wiedzieć. To powiedziawszy, jeśli jedna opcja jest bardziej zoptymalizowana niż inna, zakładam, że dobrze jest wiedzieć i nabrać nawyku używania tej metody. (Plus, cóż, byłem po prostu ciekawy odpowiedzi) - DA.
Ś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 polegasz na swoich efektach ubocznych, na przykład. - Rob
Oto kolejne pytanie dotyczące "oceny zwarć": stackoverflow.com/questions/1232603/... - David
@ David. Dzięki! Interesujące czytanie. - DA.


Odpowiedzi:


The && operator "zwarcia" - to znaczy, jeśli lewy warunek jest fałszywy, nie przejmuje się ocenianiem właściwego.

Podobnie, || Zwarcie operatora, jeśli lewy warunek jest prawdziwy.

EDYCJA: Nie powinieneś martwić się wydajnością, dopóki nie przetestujesz i nie określisz, że to jest problem. Przedwczesna mikrooptymalizacja jest zmorą łatwości konserwacji.


112
2017-12-18 20:28



Doskonała odpowiedź (zarówno część techniczna, jak i kwestia zarządzania). dzięki! - DA.
Jeśli kiedykolwiek chciałbyś, aby wykonał wszystkie części instrukcji boolowskiej, możesz użyć & i | dla i lub w perspektywie - Zoidberg
Ten warunek niekoniecznie zawsze dotyczy wydajności. Czasami możesz wykonać kontrolę zerową i powiedzieć, że jeśli kontrola zerowa jest warunkiem a, a następnie spróbujesz zrobić (b == wartość + 1) dla drugiej kontroli, dostaniesz błąd, jeśli wszystkie trzy warunki, jeśli warunki zostały sprawdzone. - infocyde
Rzeczywiście, zwarcie nie dotyczy wydajności. Pierwotne pytanie dotyczyło jednak punktu widzenia wydajności. - Anon.
bardzo dobrze. Wykonanie tego rodzaju mikro optymalizacji (między innymi) może mieć duży wpływ na pętlę zdarzeń przewijania, powiedzmy o wyliczaniu paralaksy wielu elementów na przykład lub nawet lepkim pasku. weź to ex: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop) drugim warunkiem jest bardziej kosztowna kalkulacja, pierwsza to po prostu wartość logiczna. :) - antoni


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

Jeśli mamy 3 zmienne typu Boolean, a, b, c to mikrooptymalizacja.

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

if (takesSeconds () && takesMinutes ())

jest znacznie lepszy niż

if (takesMinutes () && takesSeconds ())

jeśli obaj są równie prawdopodobne, że zwrócą fałsz.


11
2017-12-18 21:21





Dlatego możesz robić w kodzie javascript, jak

var x = x || 2;

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


9
2017-12-18 20:32



Może to zadziałać, nawet jeśli JS nie obsługuje oceny zwarcia. - p.s.w.g
Czy to odpowiednik trójskładnikowego? - Mark Carpenter Jr


Na wypadek, gdyby ktoś zastanawiał się, czy istnieje sposób wymusić ocenę wszystkich warunków, w niektórych przypadkach operatory bitowe & i | może być użyte

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

Powinny one być używane bardzo ostrożnie ponieważ operatory bitowe są operacjami arytmetycznymi, które działają na pojedynczych bitach swojego operandu i nie zawsze mogą działać jako wersja "bez zwarcia" && i || 

Przykład:

-2147483648 && 1 = 1 

ale

-2147483648 & 1 = 0

Mam nadzieję, że pomaga to komuś, kto przyjechał tutaj szukając takich informacji (jak ja) i dzięki @Maxowi za korektę i kontrprzykład


9
2017-09-21 10:33



Ta odpowiedź jest błędna. & i | są operatorem bitowym, NIE są to "wersje bez zwarć" && i || '. Operatory bitowe to operatory arytmetyczne, które działają na pojedynczym bitach swojego operandu. Przykład: -2147483648 && 1 = 1, ale -2147483648 i 1 = 0. Więcej informacji tutaj: en.wikipedia.org/wiki/Bitwise_operation - Max
@Max faktycznie nie wiedziałem tego, używałem tego (co teraz nazywam "sztuczką") od kiedy uczyłem się C. Na szczęście takie wejścia, które złamałyby mój kod nigdy się nie pojawiły. Poprawiłem odpowiedź, jestem ci winien - ivcandela
dzięki za poprawienie odpowiedzi :-) - Max
@DJDaveMark Przepraszam, nie mogłem dostać twojego false && (alert("")) rozwiązanie do pracy: / - ivcandela
@ivcandela Ja też nie. Gdybym nie był na moim telefonie, wypróbowałbym go pierwszy; o) Szkoda, że ​​nie możesz edytować komentarzy. Właśnie go usunąłem i dodałem kolejny poniżej - DJDaveMark


Sprawdza tylko wszystkie warunki, jeśli pierwsze są prawdziwe, przetestuj je dla siebie:

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

7
2017-12-18 20:29





To zwarcie - tylko a i b zostaną porównane w twoim przykładzie.


3
2017-12-18 20:29





Kończy się po zobaczeniu, że b nie jest równe jedności.


2
2017-12-18 20:28





Kolejny powód, dla którego zatrzymanie oceny z 1 lub więcej parametrami po lewej stronie.

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

druga ocena opiera się na tym, że pierwsza z nich jest prawdziwa i nie będzie generować błędu kompilacji, jeśli response.authResponse ma wartość null lub undefined itd., ponieważ pierwszy warunek nie powiódł się.

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


2
2018-05-07 00:50





Dla każdego, kto jest na tym pytaniu zdezorientowany, ponieważ nie widzi zwarcia podczas używania || w połączeniu z ? operator taki jak poniżej:

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

wydaje się, że zasada zwarcia nie działa. Dlaczego ocenia drugi termin || (prawda? 2: 3), kiedy pierwszy jest prawdziwy? Okazuje się, że jest to problem kolejności operacji, ponieważ powyższy jest odpowiednikiem

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

z || oceniane jako pierwsze i ? oceniane jako drugie. Prawdopodobnie chcesz:

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


0
2017-09-12 04:06