Carlos Brando

Nome do Jogo

Isto é um bug no Javascript?

Javascript é uma linguagem controversa. Muitos programadores adoram trabalhar com ela, mas com certeza o número de programadores que a odeiam é maior ainda. Não importa se você está no primeiro ou no segundo grupo, se você é um desenvolvedor web simplesmente não pode evitá-la.

Eu particularmente sempre estou em cima do muro quando o assunto é Javascript, já passei por momentos bem agradaveis criando coisas com esta linguagem, mas também já me irritei com algumas caracteristicas ruins da sua implementação em muitas outras ocasiões.

O fato é que para se dar bem com Javascript é importante conhecer um pouco mais da linguagem do que o usual. Mas a maioria dos programadores só estão interessados em conhecer o suficiente da linguagem para realizar pequenas tarefas e criar alguns scripts simples (Ctrl+C e Ctrl+V). Assim, quando alguma coisa imprevista acontece na execução do código, logo jogamos a culpa no pobre Javascript.

Em uma dessas madrugadas em claro, eu comecei a enumerar alguns trechos de código que parecem bugs, mas não são. Segue uma explicação sobre cada um deles e algumas dicas para evitar resultados inesperados. E antes que atirem pedras em mim, os subtítulos não devem ser levados a sério.

Javascript não sabe somar

1
2
>>> 0.1 + 0.2
0.30000000000000004

Números em Javascript são representados internamente com 64 bits e cada número pode ter no máximo 17 dígitos significativos. Isto tem algumas consequências interessantes como demonstrado no exemplo acima. É preciso ser bem cuidadoso com certos cálculos, principalmente quando a precisão é algo muito importante para o aplicativo.

Javascript não sabe somar - parte 2

1
2
3
4
5
>> "3" + 4 + 5
=> 345

>> 3 + 4 + "5"
=> 75

No Javascript, o operador de soma (+) é usado tanto para somar valores numéricos como também para concatenar strings. Precisamos estar atentos a seguinte regra: durante uma operação de soma, quando um dos valores é do tipo string, então tudo é convertido para este mesmo tipo e uma concatenação é realizada.

No primeiro exemplo, como iniciamos a soma com um string, todos os valores seguintes são imediatamente convertidos para este mesmo formato e depois são concatenados. Já no segundo exemplo, temos inicialmente uma soma numéria (3 + 4 = 7) que é realizada normalmente, mas como a próxima soma a ser realizada não será com outro valor número, mas sim com o string "5", então o Javascript realiza a conversão do primeiro resultado e em seguida realiza uma concatenação com os valores, devolvendo no final o string "75".

Javascript não sabe converter string para números

1
2
3
4
5
>>> parseInt("010")
8

>>> parseInt("010", 10)
10

O método parseInt é muito utilizado e tem por objetivo converter strings em números inteiros. Basicamente o método aceita dois parâmetros: o primeiro é um string contendo o valor a ser convertido e o segundo é um inteiro que representa a base (decimal, binário, hexadecimal, etc.) na qual o string em questão está sendo representado.

O problema aqui é que alguns livros e sites costumam explicar que o valor padrão da base (para quando ele não é informado) é 10, o que não é necessariamente uma verdade. Quando não informamos a base (radix) ou a definimos com o valor 0, então o método utiliza a seguinte regra:

  • Se o string que estamos convertendo iniciar com "0x", então o método assumirá a conversão com a base 16 (hexadecimal).
  • Se o string começar com "0" (como no primeiro exemplo) a base utilizada será 8 (octal).
  • Se o string iniciar com qualquer outro valor numérico, então a base padrão será 10 (decimal).
  • E se o primeiro caractere do string não puder ser convertido para um número, então parseInt retornará NaN. (“not a number”).

Desta forma, a regra é sempre informar a base na qual a conversão deve ser realizada, exatamente como foi feito no segundo exemplo.

Javascript não sabe fazer comparações

1
2
>> 1 == true
=> true

Podemos realizar comparações em Javascript com os símbolos <, >, <= e >=. Eles funcionam tanto para numerais como para strings. Mas quando o assunto é a comparações de igualdade, precisamos prestar atenção a alguns fatores.

O operador de igualdade duplo realiza uma coerção de tipos caso você esteja comparando dois valores de tipos diferentes, como acontece no exemplo acima. Embora aparentemente este seja um resultado normal, em outros casos podemos ter resultados inesperados, como na seguinte comparação:

1
2
>> null == false
=> false

A linguagem também conta com um operador de igualdade tripo, que ignora a coerção de tipos:

1
2
>> 1 === true
=> false

Eu particularmente tenho como regra sempre utilizar o operador triplo ao realizar comparações de valores, isto tem me ajudado a evitar alguns erros de interpretação ao analisar o código e eventuais bugs decorrentes desta característica da linguagem.

Javascript também não sabe contar

1
2
3
4
>> var a = ["dog", "cat", "hen"];
>> a[100] = "fox";
>> a.length
=> 101

A propriedade length de objetos do tipo array em Javascript sempre retornará um número acima da maior posição do array e não necessariamente a quantidade de itens no objeto, conforme você pôde ver no exemplo acima.

Se você tentar recuperar o valor em uma posição não existente no array ele devolverá undefined.

Eu amo Javascript

Javascript possui muitas características realmente boas, e da mesma forma também possui algumas implementações realmente ruins (pretendo falar sobre isto em outro artigo). Por isto é importante gastar um pouco mais de tempo estudando mais a fundo o comportamento da linguagem. Depois de entender como algumas coisas realmente funcionam, descobrimos que nem tudo é bug.

Estas são apenas algumas poucas curiosidades que consegui coletar em alguns minutos brincando com a linguagem, você conhece mais alguma?

Comments