ventojs / vento

🌬 A template engine for Deno & Node
https://vento.js.org/
MIT License
212 stars 12 forks source link

Unexpected equality comparison difference between `==` and `===` #83

Closed uncenter closed 6 days ago

uncenter commented 6 days ago

I'm struggling to understand why this equality check is different between the == and === in the following snippet:

<ul>
  {{ set items = ['A', 'B', 'C'] }}
  {{ for index, item of items }}
    <li>{{ item }}</li>
    {{ set isLast = index == (items.length - 1) }}
    {{ index }} == {{ items.length - 1 }} = {{ isLast }}
    {{# But using triple equals... #}}
    {{ set isLast = index === (items.length - 1) }}
    {{ index }} === {{ items.length - 1 }} = {{ isLast }}
  {{ /for }}
</ul>

🔗 Playground

The output of the above is:

A
0 == 2 = false 0 === 2 = false
B
1 == 2 = false 1 === 2 = false
C
2 == 2 = true 2 === 2 = false

As you can see on the last line for C, the double equals (==) compares 2 and 2 and evaluates to true, wheres the triple equals (===) compares the same 2 and 2 and evaluates to false.

oscarotero commented 6 days ago

Internally, the function to convert a value to iterator (that will be used then in the for) use Object.entries to get the key and value of an array: https://github.com/ventojs/vento/blob/main/plugins/for.ts#L61-L63

The keys are always returned as strings. For example:

Object.entries([1, 2, 3])
// [ "0", 1 ], [ "1", 2 ], [ "2", 3 ] ]

This is not what most people would expect, so I'm going to fix it.

oscarotero commented 6 days ago

fixed in v1.12.12

uncenter commented 6 days ago

Instead of Object.entries(item).map(([key, value]) => [parseInt(key, 10), value]) you should just be able to do item.map((value, index) => [index, value]).

oscarotero commented 6 days ago

@uncenter You're absolutely right. I can't belive I missed that 🤦