Atribuição encadeada de variáveis com operadores em JavaScript
Eu quero fazer algo com algumas variáveis usando operadores em rápida sucessão. Eu não achoque Eu quero fazer é importante como tal; minha pergunta é mais sobre os fundamentos da avaliação JavaScript.
Nos três exemplos abaixo, eu tento usar a adição para alterar os valores de duas variáveis. No entanto, nem todos executam como eu (talvez ingenuamente) esperado.
OPERAÇÕES COMO TRÊS DECLARAÇÕES SEPARADAS
var a = 9, b = 2;
a += b; b += a; a += b;
// a === 24, b === 13
OPERAÇÕES SEPARADAS PELO OPERADOR COMMA
var a = 9, b = 2;
a += b, b += a, a += b;
// AS EXPECTED: a === 24, b === 13
OPERAÇÕES EM UMA DECLARAÇÃO / EXPRESSÃO
var a = 9, b = 2;
a += (b += (a += b));
// BUT HERE WE GET THIS: a === 22, b === 13
No último exemplo,b
avalia como esperado, masa
avalia para um número dois curto do que aparece nos dois primeiros exemplos.
Eu acho que isso é porque tudo nos parênteses retorna o valor correto, mas é finalmente adicionado ao valor original dea
, isto é9
, em vez do valor sugerido por(a += b)
anteriormente em precedência que seria11
.
Eu tenho procurado por que isso pode estar em FlanaganJavaScript: o guia definitivo (6ª ed.), (Particularmente em 4.11.1 "Atribuição com operação"), mas não encontrou nada lá. Crockford não parece mencioná-lo explicitamente emAs boas partes ou. Eu usei vários termos de pesquisa para tentar encontrar mais informações sobre esse comportamento. Alguém pode me dizer o que esse fenômeno é chamado ou me apontar algumas informações sobre esse comportamento (supondo que seja esperado) ou o que eu poderia estar fazendo errado (supondo que não seja)?
NB Estou ciente de que os parênteses no exemplo 3 podem ser redundantes, pois, pelo que entendi, a precedência de atribuição vai da direita para a esquerda de qualquer maneira. Mas achei que tê-los ali tornaria o exemplo mais fácil de falar.
ATUALIZARA julgar pelas respostas abaixo, acho que minha confusão sobre esse assunto na verdade se deve a ter absorvido alguns parágrafos do livro de Flanagan, possivelmente incorretamente:
Na maioria dos casos, a expressão:
a op= b
Ondeop é um operador, é equivalente à expressão:
a = a op b
Na primeira linha, a expressãoa
é avaliado uma vez. No segundo, é avaliado duas vezes. Os dois casos diferem apenas se o ladoa
inclui efeitos colaterais, como uma chamada de função ou um operador de incremento. As duas atribuições a seguir, por exemplo, não são as mesmas:
data[i++] *= 2
data[i++] = data[i++] * 2
Tomei isso para significar que meu exemplo de uma linha deveria produzir os mesmos resultados que os outros dois, porque:
Flanagan menciona duas avaliações que ocorrem ema = a op b
ao contrário de um, implicando isso é de fato diferente paraa op= b
Ondea
não é avaliado como umlval
a direita.Assumi o operador de atribuição que usei (por ex.a += b
) contaria como um efeito colateral.IMHO, eu acho que Flanagan fez isso confuso e parece contradizer o que está na convenção ECMAScript (como colado abaixo porpocka), mas poderia ser a minha leitura / má interpretação. O que ele está dizendo é incorreto ou simplesmente não está claro? Ou é só comigo?