Como o JavaScript tratar o operador ++?
-
23-08-2019 - |
Pergunta
JavaScript faz conversões automáticas funky com objetos:
var o = {toString: function() {return "40"; }};
print(o + o);
print((o+1)+o);
print((o*2) + (+o));
imprimirá:
4040
40140
120
Isto porque +, se qualquer um dos argumentos são objetos / cordas, vai tentar converter todos os argumentos para cordas, em seguida, concatenar-los. Se todos os argumentos são números, adiciona-los juntos. * E unária + converter objetos em números usando toString (bem como valueOf, não mostrado aqui).
O que significa JavaScript fazer para o operador ++?
Solução
A partir ECMAScript Language Specification
11,3 Postfix Expressões
Sintaxe
PostfixExpression:
- LeftHandSideExpression
- LeftHandSideExpression [sem LineTerminator aqui] ++
- LeftHandSideExpression [sem LineTerminator aqui] -
11.3.1 Postfix Increment Operador
A produção PostfixExpression: LeftHandSideExpression [não LineTerminator aqui] ++ é avaliado da seguinte forma:
- Avaliar LeftHandSideExpression.
- Chamada GetValue (Resultado (1)).
- Chamada tonumber (Resultado (2)).
- Adicione o valor de 1 para Resultado (3), utilizando as mesmas regras para o operador + (Seção 11.6.3).
- Chamada PutValue (Resultado (1), Resultado (4)).
- Voltar Resultado (3).
Esta é pseudo código javascript de como postInc funciona:
function postInc(a) {
var x = +a; // Converts a to a number, Section 11.4.6 Unary + Operator
a = x + 1;
return x;
}
Edit: Como mikesamuel disse: não é parseInt. Atualizado para refletir isso.
Outras dicas
O código a seguir ilustra bem isso:
var a = {toString: function() {return "40"; }};
nl(typeof a);
nl(typeof +a);
nl(typeof a);
nl(typeof (a++));
nl(a);
nl(typeof a);
A saída é:
object
number
object
number
41
number
Unários mais converte o objeto em um número e não modificá-lo. A ++ primeiros convertidos o objecto para um número,
Esta opõe-se a uma outra solução possível, onde a ++ seria primeiro devolver o objecto, e, em seguida, efectuar a conversão para um número e incrementação.
O operador ++
faz uma conversão "tonumber" (basicamente uma combinação de regras do tipo ea função valueOf). Basicamente, para qualquer expressão resolve
resolveExpression++
As medidas tomadas pelo motor JS são
<temp> = toNumber(resolveExpression);
resolveExpression = <temp> + 1;
<result> = <temp>
Para expressões resolver não-atômicas, por exemplo. base.resolve++
ou base["resolve"]++
, etc. base
é resolvido apenas uma vez e depois reutilizadas. Em qualquer caso sane isso é irrelevante, no entanto, é importante se o valor que está sendo incrementado é um objeto com uma implementação valueOf que muda o objeto base.
por exemplo.
base = {};
base.value = {valueOf:function(){base = {}; return 5;}}
base.value++;