O que uma vírgula faz em expressões JavaScript?

89

Se eu usar:

1.09 * 1; // returns "1.09"

Mas se eu usar:

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

Eu sei que 1,09 não é um número.

O que a vírgula faz na última parte do código?

Mais exemplos

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
fonte
1
Estou surpreso que 09 não está falhando para '9' ilegal em octal literal.
recursivo
7
@recursive - qualquer 9 na representação octal resulta em um fallback para decimal.
Yuval Adam
Não confunda a vírgula em uma lista de argumentos. alertleva apenas um argumento. Qualquer coisa depois disso é descartada.
Andrew
@Andrew: sim, é descartado por alert (), que leva apenas um argumento, mas será executado! Isso é estranho. Obrigado.
Topera
1
@Topera: nada estranho se você pensar da perspectiva de JS. Em JS, você não precisa especificar sua lista de argumentos em sua declaração de função (você pode usar o argumentsobjeto, que pode ter qualquer comprimento). Mesmo com o JS compilado moderno, não haveria como dizer com antecedência quantos argumentos uma função levaria. Considere o seguinte: function test() { args=[]; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i] + 1); } ;o interpretador teria que saber como a função estava sendo usada para saber quantos argumentos seriam necessários. Em vez disso, avalia tudo.
Andrew

Respostas:

95

O operador vírgula avalia seus dois operandos (da esquerda para a direita) e retorna o valor do segundo operando.

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

Por exemplo, a expressão é 1,2,3,4,5avaliada como 5. Obviamente, o operador vírgula é útil apenas para operações com efeitos colaterais.

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

Yuval Adam
fonte
2
Eles tiraram de C. Acho que só é útil para expressões que têm efeitos colaterais.
Radomir Dopieralski
3
Não consigo pensar em muitos casos em que o operador vírgula é usado para qualquer efeito, exceto salvar caracteres (reduzir) ou ofuscar código.
user17753
1
@ user17753 pode ser usado legitimamente na seção separada por ponto e vírgula de um forloop.
Cyoce
1
@Cyoce: Embora isso seja verdade, falando de modo geral, essa lógica é mais claramente executada no corpo do loop. Algumas pessoas dirão que seu caminho permite vários continuepontos sem duplicação, mas você não deve ter vários continuepontos.
Lightness Races in Orbit
@ user17753 Você está certo; tentando entender um pequeno trecho de código reduzido é o motivo pelo qual estou aqui
SeldomNeedy
6

Mais alguns a considerar:

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

Douglas
fonte
7
Lol, é divertido:alert("1", alert("2", alert("3")))
Topera
1
@Andrew: Opa, atualizei minha resposta com o que pretendia usar.
Douglas
O operador vírgula avalia cada um de seus operandos (da esquerda para a direita) e retorna o valor do lastoperando.
xgqfrms de
2

Dê uma olhada aqui - a vírgula significa várias expressões / declarações. Por exemplo, em seu código, você pode usar uma linha como esta:

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

Isso declararia todas as três variáveis ​​sem escrever:

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

Espero que ajude.

dhh
fonte
22
É um pouco antigo, mas é importante notar: (1) o exemplo que você forneceu não usa o operador vírgula (as vardeclarações não usam o operador vírgula , embora seja uma vírgula) e (2) você não pode separar declarações usando os operadores de vírgula; apenas expressões são permitidas.
Qantas 94 Heavy de
2
O operador vírgula avalia seus dois operandos (da esquerda para a direita) e retorna o valor do second operando.

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

Deve ser assim!

O operador vírgula avalia cada um de seus operandos (da esquerda para a direita) e retorna o valor do lastoperando.

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

xgqfrms
fonte
4
O operador vírgula leva dois operandos, então a citação original estava correta. O que você está falando é o resultado final do aninhamento de tais expressões, mas isso significa que sua citação de substituição está sutilmente incorreta. a,b,c,dis((((a),b),c),d)
Lightness Races in Orbit
0

Adicionar / modificar propriedades a um objeto e retorná-lo na mesma linha é um possível caso de uso:

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]
// }

A função anônima acima retorna um objeto com valores aleatórios maiores que o valor de entrada ou, se não houver nenhum, com o próprio valor de entrada em uma matriz contida na biggerpropriedade.

Ainda é um açúcar sintático (como funções de seta ), mas encurta o número de linhas ... Gostaria de saber se alguns minificadores JS detectam e ajustam o código de maneira semelhante automaticamente. Execute-o em seu 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
fonte
2
Mas é claro que você não colocaria esses encantamentos enigmáticos no código de produção, certo?
Lightness Races in Orbit
@LightnessRacesinOrbit bem, direi que depende do propósito (por exemplo, ensino, código de encurtamento, nenhuma declaração de variável / função, etc.). Se você recuar como fiz acima, é perfeitamente legível ... Não consigo parar de notar que você usou a palavra "enigmática" :)
CPHPython
1
Heh, isso nem foi deliberado 😂
Lightness Races in Orbit