Une instruction javascript if avec plusieurs conditions les teste-t-elle toutes?


100

En javascript, lorsque vous utilisez une instruction if avec plusieurs conditions à tester, javascript les teste-t-il toutes indépendamment, ou sera-t-il libéré avant de les tester tous si c'est déjà faux?

Par exemple:

 a = 1
 b = 2
 c = 1

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

Est-ce que javascript testera toutes ces 3 conditions ou, après avoir vu que b n'est pas égal à 1, et est donc faux, quittera-t-il l'instruction?

Je demande du point de vue de la performance. Si, par exemple, je teste 3 sélecteurs jQuery complexes, je préfère ne pas laisser jQuery traverser le DOM 3 fois s'il est évident via le premier qu'il va retourner FALSE. (Dans ce cas, il serait plus judicieux d'imbriquer 3 instructions if).

ADDENDUM: Plus d'une curiosité, quel est le terme approprié pour cela? Je remarque que beaucoup d'entre vous utilisent le terme «court-circuit». Aussi, est-ce que certaines langues font cela et d'autres non?


@Josh: J'apprécie complètement l'idée qu'il s'agit de micro-optimisation. Ce qui est bon à savoir. Cela dit, si une option est plus optimisée qu'une autre, je suppose qu'il est bon de savoir et de prendre l'habitude d'utiliser ladite méthode. (De plus, eh bien, j'étais juste vraiment curieux de savoir la réponse aussi)
DA.

21
À proprement parler, ce n'est pas une optimisation prématurée. Dans les langages avec logique de court-circuit, il est important de savoir dans quelles conditions certaines méthodes ne seront pas exécutées; si vous comptez sur leurs effets secondaires, par exemple.
Rob

5
Voici une autre question sur "l'évaluation des courts-circuits": stackoverflow.com/questions/1232603/…
David

@David. Merci! Lecture intéressante.
DA.

Réponses:


151

L' &&opérateur «court-circuite» - c'est-à-dire que si la condition de gauche est fausse, il ne prend pas la peine d'évaluer la bonne.

De même, l' ||opérateur court-circuite si la condition de gauche est vraie.

EDIT: Cependant, vous ne devriez pas vous soucier des performances tant que vous n'avez pas évalué et déterminé que c'est un problème. La micro-optimisation prématurée est le fléau de la maintenabilité.


1
Excellente réponse (à la fois la partie technique et la question de gestion). Merci!
DA.

5
Si jamais vous voulez qu'il exécute toutes les parties de l'instruction booléenne, vous pouvez utiliser & et | pour et et ou repspectivement
Zoidberg

25
Cette condition ne concerne pas nécessairement toujours les performances. Parfois, vous pouvez faire une vérification nulle et dire si votre vérification nulle est la condition a, puis vous essayez de faire a (b == valeur + 1) pour votre deuxième vérification, vous obtiendrez une erreur si les trois conditions si les conditions étaient vérifiées.
infocyde

4
En effet, le court-circuit n'est pas une question de performances. La question initiale, cependant, se posait du point de vue de la performance.
Anon.

1
très bon. Faire ce type de micro-optimisation (entre autres) peut avoir un impact important dans une boucle d'événement de défilement, disons pour le calcul de parallaxe de plusieurs éléments par exemple ou même une barre collante. if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)Prenons cet exemple: la deuxième condition est un calcul plus coûteux, la première est juste un booléen. :)
antoni

13

Du point de vue des performances, il ne s'agit pas d'une micro-optimisation.

Si nous avons 3 variables booléennes, a, b, c c'est une micro-optimisation.

Si nous appelons 3 fonctions qui renvoient des variables booléennes, chaque fonction peut prendre du temps, et non seulement il est important de connaître ces courts-circuits, mais dans quel ordre. Par exemple:

if (takesSeconds() && takesMinutes())

est bien mieux que

if (takesMinutes() && takesSeconds())

si les deux sont également susceptibles de renvoyer false.


12

C'est pourquoi vous pouvez faire du code javascript comme

var x = x || 2;

Ce qui signifierait que si x est indéfini ou 'faux', la valeur par défaut est 2.


3
Cela pourrait fonctionner même si JS ne prenait pas en charge l'évaluation des courts-circuits.
pswg

1
Est-ce l'équivalent d'un ternaire?
Mark Carpenter Jr

10

Dans le cas où quelqu'un se demande s'il y a un moyen de forcer l'évaluation de toutes les conditions, dans certains cas , les opérateurs binaires &et |peut être utilisé

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

Ceux-ci doivent être utilisés avec beaucoup de précaution car les opérateurs bit à bit sont des opérateurs arithmétiques qui fonctionnent sur des bits uniques de leur opérande et ne peuvent pas toujours fonctionner comme une version "sans court-circuit" de &&et||

Exemple:

-2147483648 && 1 = 1 

mais

-2147483648 & 1 = 0

J'espère que cela aide quelqu'un qui est arrivé ici à la recherche d'informations comme celle-ci (comme moi) et merci à @Max pour la correction et le contre-exemple


1
Cette réponse est fausse. & et | sont des opérateurs binaires, ce ne sont PAS des «versions sans court-circuit de && et ||». Les opérateurs au niveau du bit sont des opérateurs arithmétiques qui fonctionnent sur des bits uniques de leur opérande. Exemple: -2147483648 && 1 = 1 mais -2147483648 & 1 = 0. Plus d'informations ici: en.wikipedia.org/wiki/Bitwise_operation
Max

1
@Max en fait je ne le savais pas, j'utilise ça (ce que j'appelle maintenant "truc") depuis que j'étudiais C. Heureusement, de telles entrées qui auraient cassé mon code ne sont jamais apparues. J'ai corrigé ma réponse, je vous dois
ivcandela

@DJDaveMark désolé, je n'ai pas pu faire fonctionner votre false && (alert(""))solution: /
ivcandela

@ivcandela Moi non plus. Si je n'étais pas sur mon téléphone, je l'aurais testé en premier; o) Dommage que vous ne puissiez pas modifier les commentaires. Je viens de le supprimer et d'en ajouter un autre ci
DJDaveMark

Le moyen le plus simple et le meilleur pour forcer l'évaluation est d'enregistrer les résultats dans des variables puis de les tester par rapport aux variables, c'est-à-dire:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

Il ne testera toutes les conditions que si les premières sont vraies, testez-le vous-même:

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

3

Il court-circuits - seuls a et b seront comparés dans votre exemple.


3

Une autre raison pour laquelle arrêter l'évaluation avec 1 ou plusieurs paramètres à gauche.

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

la deuxième évaluation repose sur le fait que la première est vraie et ne lèvera pas d'erreur de compilation si response.authResponse est nulle ou indéfinie, etc. parce que la première condition a échoué.

D'autres langages ont eu ce problème au début et je pense que c'est une approche standard dans la construction de compilateurs maintenant.


2

Il sort après avoir vu que b n'est pas égal à un.


2

Pour toute personne sur cette question confuse parce qu'elle ne voit pas le comportement de court-circuit lors de l'utilisation d'un ||en conjonction avec un ?opérateur comme celui-ci:

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

il semble que la règle des courts-circuits ne fonctionne pas. Pourquoi évalue-t-il le deuxième terme du ||(vrai? 2: 3) alors que le premier est vrai? Cela s'avère être un problème d'ordre des opérations car ce qui précède est l'équivalent de

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

avec le ||premier évalué et le ?deuxième évalué. Ce que vous voulez probablement, c'est:

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.