Lucas Santos 🇧🇷🇸🇪 || formacaots.com.br 💎 Profile picture
I do LOTS of code in #TypeScript and #JavaScript | 🏆 @GoogleDevExpert | 🏆 @MVPAward | 🏆 #DockerCaptain | 🏆 #ImpulserExpert | 🧠 ISTJ-A | #FormacaoTS.com.br

Apr 3, 2022, 31 tweets

VOCÊS ESTÃO PREPARADOS PARA ESSA THREAD? Vou passar ponto por ponto de todas as coisas que estão escritas aqui e vou explicar uma por uma pra NÃO FICAR NENHUMA DÚVIDA de que o JS não faz isso porque é uma falha da linguagem.

Isso eu expliquei durante a minha live no @cafedebug () o que acontece é que o NaN é um número porque, assim como o Pi, ou o número de Euler, ele é somente um símbolo que representa um valor que não pode ser representado como um número +

Da mesma forma como fazemos na matemática, quando não podemos representar um número, damos a esse número um símbolo, números complexos são o melhor exemplo disso, e nem por isso deixam de ser números.

Além disso essa é outra que sempre colocam, e isso está descrito na especificação do ECMA262 na seção 7.2.14 - item 7. Isso não é estranho, é seguir a regra. 262.ecma-international.org/12.0/#sec-abst…

Além disso a IEEE-754 (a mesma dos float points) ajuda a explicar isso de uma forma bem clara. stackoverflow.com/questions/1565…

Again, números, toda operação matemática no JS ou fora dele está sujeita a arredondamento (262.ecma-international.org/12.0/#sec-nume…), se você não quer que isso aconteça, use o BigInt developer.mozilla.org/en-US/docs/Web…

Esse eu vou abordar como um grupo inicialmente, porque a saída é óbvia essas duas somas parecem ser iguais pra você? Se você quiser entender mais porque isso não é um problema só do #JavaScript MAS DE TODAS AS LINGUAGENS temos um site só pra isso 0.30000000000000004.com

Agora sobre esse aqui especificamente, como você pode ver no tweet anterior, o resultado não é 0.3, então a saída está correta. O problema aqui é muito maior do que todos nós e eu falo disso nesse ponto do vídeo ++

A questão aqui é que a gente só consegue representar números com uma acurácia perfeita em um sistema de base N se o número for um múltiplo dos fatores primos de N, ou seja, no caso da base 10 (comum), os fatores primos são 2 e 5, então todo o valor que possa ser escrito ++

Como uma fração de 2 ou 5, como 1/2 ou 1/5, ou até seus multiplos, como 0.1 que é 1/10, ou 2/10 não vão possuir restos e serão divisões perfeitas, no entanto, números que não são multiplos desses fatores vão ser dízimas, como dividir 10/3 já que 3 não é um fator, temos 3.333... +

Quando estamos tratando com binário, os únicos fatores são muito mais restritos, portanto, os valores 0.1 e 0.2 são representados como uma soma de frações que apresentam o valor mais próximo do resultado final (algo como essa imagem, matemáticos, por favor me corrijam) ++

Como a soma não é exata, o restante somado de 0.1 com 0.2 passa de 0.3, portanto o valor é maior.

Essa é mais complicada, porque envolve uma série de operações matemáticas. Mas a ideia é que, se formos olhar isso pela lente de uma álgebra mais abstrata, temos que GARANTIR que o resultado de uma chamada pra uma dessas funções é o esperado. E a gente faz isso com identidades +

A identidade que permite a gente ter sempre o maior número de uma lista é ter uma lista cujo único elemento é -Inf para o máximo e Inf para o mínimo, afinal qualquer número é maior que -Inf e menor que +Inf. Uma explicação mais completa aqui charlieharvey.org.uk/page/why_math_…

Como eu expliquei nessa outra thread. Somar dois arrays convertem ambos para strings, a representação de string em um array vazio é "" ou seja, concatenar duas strings vazias é ""

Mesmo caso do anterior, você já tentou dar um console.log em um objeto concatenado com uma string? O resultado é o mesmo, a diferença é que estamos somando "" com "[object Object]" que é a representação do {}

Aqui a questão é criação de escopo dinâmico. Sem parenteses, essa expressão traduz como um bloco de código vazio e uma conversão de um array para um número, basicamente como na segunda imagem (o @erickwendel_ já mostrou isso em alguns vídeos), +[] converte [] para número ++

Isso é algo que eu tenho que dar o braço a torcer, porque a representação numérica de um array vazio é sempre 0, mas a representação booleana é sempre true e isso pode confundir, mas se usarmos parenteses, temos o mesmo resultado

True converge para 1 quando convertido para número, se somarmos 3 trues é a mesma coisa que Number(true)*3 que é 3, da mesma forma de Number(true)-Number(true) é 1-1 que é 0

Eu me sinto até meio mal de explicar essa mas então, o operador de comparação abstrada (==) coerce o tipo para manter o mesmo dos dois lados, portanto true == 1 é 1==1 que é true, já a comparação estrita (===) compara TIPO e valor, 1 não é booleano, portanto...

mais uma pegadinha, se pegarmos o valor que está sendo somado dentro da expressão e começarmos a executar ele parte a parte, vamos a expressão que eu vou colocar no próximo tweet ++

O resultado é 'truefalse' que tem 9 caracteres, por isso o resultado é 9. E o porquê disso tudo você pode entender aqui github.com/denysdovhan/wt…

A parada aqui é que o operador de adição pode ser o concatenador de uma string ou uma operação de soma conforme a parte 13.8.1 da Spec do ECMA, já o operador de subtração sempre vai subtrair números, logo ele vai converter o que não é número pra números e executar a operação ++

Por isso 91-"1" é 90, porque o que está acontecendo é 91 - Number(1), já a adição chama realiza uma verificação "EvaluateStringOrNumericBinaryExpression" conforme a specificação ++ 262.ecma-international.org/12.0/#sec-addi…

Essa expressão vai produzir um valor da expressão "ApplyStringOrNumericBinaryOperator" que diz que se qualquer um dos lados for string e o operador for "+" então retorna a concatenação das strings 262.ecma-international.org/12.0/#sec-appl…

Por fim a clássica, como eu falei, eu acho errado o array convergir pra 0 quando é numérico e pra true quando é boolean, mas novamente, todos esses problemas acontecem por conta do "==", o que a gente ta vendo aqui é (+[])==0 que é 0==0, ou seja, true.

Se a gente fizer usando "===" isso vai dar false, mas se a gente converter e comparar com boolean isso também vai dar true

E chegamos ao fim 🎉 o objetivo dessa thread foi justamente pra mostrar pra galera que o JS não é esquisito, ele é perfeitamente normal de acordo com a sua própria especificação e também para incentivar a galera a ler um pouco mais antes de postar sobre isso!

Quem quiser ver as outras threads, essa foi uma:

Essa foi outra:

E logo mais vai ter vídeo lá sobre isso no canal, valeu galera! youtube.lsantos.dev

Share this Scrolly Tale with your friends.

A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.

Keep scrolling