Que fait une virgule dans les expressions JavaScript?

89

Si j'utilise:

1.09 * 1; // returns "1.09"

Mais si j'utilise:

1,09 * 1; // returns "9"

Je sais que 1,09 n'est pas un nombre.

Que fait la virgule dans le dernier morceau de code?

Plus d'exemples

if (0,9) alert("ok"); // alert
if (9,0) alert("ok"); // don't alert

alert(1); alert(2); alert(3); // 3 alerts
alert(1), alert(2), alert(3); // 3 alerts too

alert("2",
    foo = function (param) {
        alert(param)
    },
    foo('1')
)
foo('3'); // alerts 1, 2 and 3
Topera
la source
1
Je suis surpris que 09 n'échoue pas pour un «9» illégal dans le littéral octal.
récursif
7
@recursive - tout 9 dans la représentation octale entraîne un retour en décimal.
Yuval Adam
Ne confondez pas la virgule dans une liste d'arguments. alertne prend qu'un seul argument. Tout ce qui suit est jeté.
Andrew
@Andrew: oui, est rejeté par alert (), cela ne prend qu'un seul argument, mais il sera exécuté! C'est bizarre. Merci.
Topera
1
@Topera: pas vraiment bizarre si vous y pensez du point de vue de JS. Dans JS, vous n'avez pas à spécifier votre liste d'arguments dans votre déclaration de fonction (vous pouvez utiliser l' argumentsobjet à la place, qui peut être de n'importe quelle longueur). Même avec le JS compilé moderne, il n'y aurait aucun moyen de dire à l'avance combien d'arguments une fonction prendrait. Considérez ceci: function test() { args=[]; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i] + 1); } ;l'interpréteur devrait savoir comment la fonction était utilisée pour savoir combien d'arguments cela prendrait. Au lieu de cela, il évalue tout.
Andrew

Réponses:

95

L'opérateur virgule évalue ses deux opérandes (de gauche à droite) et renvoie la valeur du deuxième opérande.

Source: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special_Operators/Comma_Operator

Par exemple, l'expression est 1,2,3,4,5évaluée à 5. De toute évidence, l'opérateur virgule n'est utile que pour les opérations avec des effets secondaires.

console.log(1,2,3,4,5);
console.log((1,2,3,4,5));

Yuval Adam
la source
2
Ils l'ont pris de C. Je pense que ce n'est utile que pour les expressions qui ont des effets secondaires.
Radomir Dopieralski
3
Je ne peux pas penser à de nombreux cas où l'opérateur virgule est utilisé pour n'importe quel effet, mais en enregistrant des caractères (minifying) ou en obscurcissant le code.
user17753
1
@ user17753 il peut être utilisé légitimement dans la section séparée par des points-virgules d'une forboucle.
Cyoce
1
@Cyoce: Bien que ce soit vrai, d'une manière générale, une telle logique est plus clairement exécutée dans le corps de la boucle. Certaines personnes prétendront alors que leur chemin permet plusieurs continuepoints sans duplication, mais alors vous ne devriez pas avoir plusieurs continuepoints.
Courses de légèreté en orbite
@ user17753 Vous êtes sur l'argent; essayer de comprendre un petit extrait de code minifié est la raison pour laquelle je suis ici
SeldomNeedy
6

Quelques autres à considérer:

console.log((0, 9));
console.log((9, 0));
console.log(("foo", "bar"));

Douglas
la source
7
Lol, c'est amusant:alert("1", alert("2", alert("3")))
Topera
1
@Andrew: Oups, j'ai mis à jour ma réponse avec ce que je voulais utiliser.
Douglas
L'opérateur virgule évalue chacun de ses opérandes (de gauche à droite) et renvoie la valeur de l' lastopérande.
xgqfrms
2

Jetez un œil ici - la virgule représente plusieurs expressions / déclarations. Par exemple, dans votre code, vous pouvez utiliser une ligne comme celle-ci:

var a=0, b=0, c=0;

Cela déclarerait les trois variables sans écrire:

var a=0;
var b=0;
var c=0;

J'espère que cela pourra aider.

dhh
la source
22
C'est un peu vieux, mais important à noter: (1) l'exemple que vous avez fourni n'utilise pas l'opérateur virgule (les vardéclarations n'utilisent pas l' opérateur virgule , même si c'est une virgule) et (2) vous ne pouvez pas séparer déclarations utilisant les opérateurs virgule; seules les expressions sont autorisées.
Qantas 94 Heavy
2
L'opérateur virgule évalue ses deux opérandes (de gauche à droite) et renvoie la valeur de l' second opérande.

https://stackoverflow.com/a/3561056/5934465

Ça devrait être comme ça!

L'opérateur virgule évalue chacun de ses opérandes (de gauche à droite) et renvoie la valeur de l' lastopérande.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

xgqfrms
la source
4
L'opérateur virgule prend deux opérandes, donc le guillemet d'origine était correct. Ce dont vous parlez est le résultat final de l'imbrication de telles expressions, mais cela signifie que votre devis de remplacement est subtilement mal orthographié. a,b,c,dis((((a),b),c),d)
Courses de légèreté en orbite
0

Ajouter / modifier des propriétés à un objet et le renvoyer dans la même ligne est un cas d'utilisation possible:

console.log(
  ((x) => (o = {biggerCond: r => r >= x},
           o.r5 = Array.from(window.crypto.getRandomValues(new Uint16Array(5))),
           o.isAnyBigger = o.r5.some(o.biggerCond),
           o.bigger = o.isAnyBigger ? o.r5.filter(o.biggerCond) : [x], o )
  )(5e4)
);
// Example
// {
//   bigger: [58414, 56500, 63397],
//   isAnyBigger: true,
//   isBiggerCond: r => r >= x,
//   r5: [58414, 12015, 56500, 63397, 43861]
// }

La fonction anonyme ci-dessus renvoie un objet avec des valeurs aléatoires plus grandes que la valeur d'entrée ou, s'il n'y en a pas, avec la valeur d'entrée elle-même dans un tableau contenu dans la biggerpropriété.

C'est toujours du sucre syntaxique (comme les fonctions fléchées ), mais cela raccourcit le nombre de lignes ... Je me demande si certains minificateurs JS détectent et ajustent automatiquement le code de la même manière. Exécutez-le dans votre console:

((x)=>(o={biggerCond:r=>r>=x},o.r5=Array.from(window.crypto.getRandomValues(new Uint16Array(5))),o.isAnyBigger=o.r5.some(o.biggerCond),o.bigger=o.isAnyBigger?o.r5.filter(o.biggerCond):[x],o))(5e4)
CPHPython
la source
2
Mais bien sûr, vous ne mettriez pas de telles incantations cryptiques dans le code de production, non?
Courses de légèreté en orbite
@LightnessRacesinOrbit bien, je dirai que cela dépend du but (par exemple l'enseignement, le raccourcissement du code, pas de déclaration de variable / fonction, etc.). Si vous le mettez en retrait comme je l'ai fait ci-dessus, il est parfaitement lisible ... Je n'arrête pas de remarquer que vous avez utilisé le mot "cryptique" :)
CPHPython
1
Heh, ce n'était même pas délibéré 😂
Courses de légèreté en orbite