The Abstract Equality Comparison Algorithm
Tags: javascript, programming, webdev, beginners
Published: 2023-03-06 04:12:24

Revisitando alguns assuntos bases do **JavaScript** percebi a necessida de aprofundar um pouco mais a teoria de como as coisas funcionam _behind the scenes_.

Vou tentar trazer aqui um resumo sobre a interação do "Algoritmo de comparação de igualdade" ou como o JavaScript chama "The Abstract Equality Comparison Algorithm" e o "Type Coercion". Em outras palavras eu quero tentar explicar como o `==`(_igual a_) entende os parâmetros passados a ele para comparação de igualdade.

Inicio esse artigo considerando que se você chegou aqui você entende o que é o `==` no JavaScript. Mas caso tenha caído aqui de paraquedas [segue um link](https://www.alura.com.br/artigos/operadores-matematicos-em-javascript) para conhecer antes de ler o meu texto.

---

## x `==` y
Sabemos então que esse operador recebe dois parâmetros e compara seus valores, simples assim, ou será que não?
Para nós que apenas vemos o resultado final é tudo muito mágico e simples mas as vezes podemos nos deparar com algumas situações (ou evitá-las) se conhecermos um poco mais como a "mágica" funciona.

Vou utilizar um exemplo que retirei do livro [You Don't Know Js](https://github.com/cezaraugusto/You-Dont-Know-JS/blob/portuguese-translation/up%20%26%20going/ch2.md#igualdade)

```
let arr1 = [1,2,3];
let arr2 = [1,2,3];
let str = "1,2,3";
```

Em um primeiro momento podemos dizer que visualmente `arr1` é igual a `arr2` e os dois são diferentes de `str`, correto?

Acontesse que quando os comparamos utilizando o `==` temos uma pequena surpresa.

```
arr1 == str; // true
arr2 == str; // true
arr1 == arr2; // false
```
Descobrimos que na verdade `arr1` é diferente de `arr2` porém os dois são iguais a `str`. Como pode isso?

Poderíamos apenas aceitar que é assim que funciona o JavaScript e seguir com nossas vidas, mas se você está curioso para entender porquê `[1,2,3] é diferente de [1,2,3]` continua lendo aqui...

---

![Curious](https://media.giphy.com/media/hS6KvugVZSAH6/giphy-downsized-large.gif)

---

Legal você ficou, vamos lá!
Cavando um pouco mais fundo esbarramos com dois outros temas: Type Coercion e The Abstract Equality Comparison Algorithm.
Abaixo vou te dar um breve resumo sobre o Type Coercion para em seguida entendermos como ele se aplica no segundo, e mais importante, tema.

## Type Coercion
O `Type Coercion` é a forma como o JavaScript converte o tipo de um valor para outro tipo de forma "automática" e implícita.

Podemos ver isso quando tentamos somar um número com um texto ou na linguagem de tipos seria um `number` com uma `string`


![12 + "20"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sap43us2ch6xqw09gkbc.png)

Nesse momento para evitar qualquer quebra na execução do código o `Type Coercion` decide que o valor `12` do tipo `number` vai ser convertido para `string` e em vez de somar ele concatena os dois valores em uma única string garantindo a execução do código.

O javaScript então se utiliza de algoritmos próprios para decidir e priorizar qual valor ele deve converter para que o código possa ser executado com sucesso.

_Não vou me prolongar mais sobre o Type Coercion porque até aqui é suficiente para entender o próximo e principal tópico. Quem sabe eu trago um artigo só sobre ele no futuro._

---

## The Abstract Equality Comparison Algorithm
Chegamos então no X da questão
![Find the X](https://media.giphy.com/media/HBWbIuHvXI2Eo/giphy.gif)
Esse algoritmo abstrato nada mais é que a forma como o javaScript aplica o `Type Coercion` no momento da comparação de `==`(igual a) e entender isso te permite manipular melhor ou com mais certeza seu código e evitar aqueles momentos onde o código funciona por pura mágica.
![Magic](https://media.giphy.com/media/NmerZ36iBkmKk/giphy.gif)

_Behind the scenes_ ele vai tentar comparar os **valores** dos paramêtros `x == y` e quando algo que não deveria acontecer, acontece, ele te da uma ajuda convertendo os tipos dos valores. Com isso ele aplica seu algoritmo de comparação de igualdade onde ele classifica prioridades de conversão e cria condições para que elas sejam aplicadas.

No tópico [11.9.3](https://262.ecma-international.org/5.1/#sec-11.9.3) da especificação do JavaScript ele institui que:

![Se o X é Object e o Y é uma String ou Number, retorna o resultado da comparação de ToPrimitive(x) == y](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6kqdg41b8yk531rtxsin.png)
_Se o X é Object e o Y é uma String ou Number, retorna o resultado da comparação de ToPrimitive(x) == y._

O que ele quer dizer com isso?
Ele ta dizendo que se no código que você escreveu `[1,2,3] == "1,2,3"` o **X**`= [1,2,3]` for um objeto e o **Y**`= "1,2,3"` for uma String ou Number ele vai tentar converter o valor de **X** _(por trás dos panos)_ para um valor primitivo usando o `Type Coercion`, que vimos anteriormente, e depois da conversão comparar os valores.

_Se você ficou confuso com a palavra **primitivo** [segue um link](https://developer.mozilla.org/pt-BR/docs/Glossary/Primitive) pra entender melhor o parágrafo anterior._

Nesse ponto começamos a ter uma boa dica para entender o motivo de `[1,2,3] ser igual a "1,2,3"` ou como em nosso exemplo `arr1 == str // true`.

Olha só! Quando utilizamos o typeof para verificar o tipo dos valores do nosso exemplo do começo desse artigo, descobrimos que o `arr1` e `arr2` são objetos e o `str` é string logo a comparação de `arr1 == str` cai na condição que o algoritmo de comparação de igualdade instituiu.
```
typeof arr1 // object
typeof arr2 // object
typeof str // string
```
Você ja deve está entendendo onde eu quero chegar... Vamos então entender nosso exemplo do início do artigo.
```
arr1 == str; // true
arr2 == str; // true
arr1 == arr2; // false
```
Na primeira linha ele compara `arr1`, que é um `object`, com `str` que é `string`, então, antes de tudo, converte `arr1` para `string` e então comparando os dois valores temos o resultado de `true` pois os dois valores são iguais no final. _E aqui quero abrir um parênteses para você entender melhor como ele faz essa conversão._

Todo valor do tipo objeto tem um método interno chamado `toString` e é justamente esse metodo que o javaScript se utiliza para fazer as conversões por meio do Type Coercion de forma implícita. Mas nós também podemos fazer de forma explícita para ficar mais visível.
```
arr1.toString() // "1,2,3"
```
Olha só, se chamamos o método toString do objeto `arr1` temos como resultado exatamente o mesmo valor da variável `str` por isso o resultado da comparação de `arr1 == str é true`, no fim eles possuem o mesmo valor. A mesmo coisa se aplica para `arr2 == str`.

A última linha de nosso exemplo diz que `arr1 == arr2 é false` e isso acontece porque a especificação [11.9.3](https://262.ecma-international.org/5.1/#sec-11.9.3) diz que ele só converte o valor do objeto caso um dos valores fosse `object` e o outro `string` ou `number`. Nessa comparação que estamos fazendo agora os dois são `object`.
```
typeof arr1 // object
typeof arr2 // object
```

Então essa comparação cai em outra condicional instituida pela especificação [11.9.3](https://262.ecma-international.org/5.1/#sec-11.9.3).

![especificação ecmascript 11.9.3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2zbn7ps4kwzeuiyrhg8.png)

Logo como ele não vai converter nem X e nem Y pois os dois são `object` ele vai retorna `false` pois o valor do objeto é ele próprio e cada objeto instanciado é diferente um do outro mesmo possuindo as mesmas propriedades.

_Se quiser entender mais sobre objetos [esse link](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Working_with_Objects) pode te ajudar._


Por fim, vimos então que uma simples comparação `==` passa por um algoritmo que vai:

1. Verificar os tipos dos valores dos parâmetros passados;
2. Ver em qual condição se encaixam;
3. Converter os tipos dos valores;
4. Para só então comparar um com o outro.

E se eu te mostrar novamente o mesmo exemplo do início desse artigo?
```
let arr1 = [1,2,3];
let arr2 = [1,2,3];
let str = "1,2,3";

arr1 == str; // true
arr2 == str; // true
arr1 == arr2; // false
```

Espero que olhando para ele agora não apenas venha na sua cabeça "não entendi mas é assim que funciona" mas que agora faça sentido para você o resultado de cada comparação entendendo o que acontece por trás dos panos e com isso possa melhorar os seus códigos.

---

## Links úteis

- [Especificação do Algoritimo de comparação de igualdade](https://262.ecma-international.org/5.1/#sec-11.9.3)
- [Especificação do metodo implícito ToPrimitive()](https://262.ecma-international.org/5.1/#sec-9.1)
- [Especificação de como o JavaScript prioriza a conversão dos valores dos objetos](https://262.ecma-international.org/5.1/#sec-8.12.8)

Se esse post te ajudou em algo, deixa um comentário ou um Like pra ajudar no engajamento :D