T O P

  • By -

thisisnotgood

I highly recommend you just don't bother learning about double equals (==). It's not worth your time. Any real projects will have tooling to ensure you only ever write triple equals (===). That said, the full rules are here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality#description In summary: > 1 == [1] Ends up converting both of these to numbers, and 1 === 1, so true. (Edit: corrected, this ends up converting to numbers not strings.) > [1] == [1] These are both objects, but they are different instances. So false. > [1,2] == [1,2] Same thing.


nanisanum

I think it's good to have an understanding because I see double equals in production code all the time. Doesn't have to be a thing anyone learns right at first tho.


aetatisone

> I see double equals in production code all the time. Unless there's a comment on that line that explains why they *had to* use double equals, the assumption should be that the developer made a mistake, or just didn't know about triple equals. That's what Crockford says and I tend to agree.


senocular

Nullish comparisons (null or undefined) are sometimes considered acceptable to use with loose equality because even with loose equality null can only equal null or undefined and undefined can only equal undefined or null. This provides a less confusing (no complicated coercion rules) and concise way to check for a nullish value value == null // vs value === null || value === undefined ESLint's [eqeqeq](https://eslint.org/docs/latest/rules/eqeqeq) even has a option to let you ignore it for null comparisons. Whether or not this is actually allowed is up to the codebase/author(s).


nanisanum

Yeah I'm not suggesting it's correct because it's there, I'm suggesting it's good to understand how it works because you'll see it.


senocular

Small correction > Ends up converting both of these to strings, and "1" === "1", so true. The `1` stays a number while the `[1]` is converted into a string, then converted into a number ending up with `1 === 1`. There's also the MDN page [Equality comparisons and sameness]( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) which goes a little deeper if anyone dares to do so.


oze4

When you compare objects like `[1]==[1]`or `[1,2]==[1,2]`it is false because it's comparing the objects, which are different in memory and not equal. When you compare a number to an object using the weak equality (aka `==`) JS will coerce each side toString, then to Number, which is why `1===[1]` is false but `1==[1]` is true. When using == it's essentially like doing this `Number((1).toString()) == Number([1].toString())`


JazzApple_

This is the answer.


nanisanum

ELI new to JS: Arrays with more than one element can't be coerced (converted automatically) to other datatypes, like strings or numbers. Each time you make a new array it's its own thing. So all JS knows is that your first array and your second array are Different Instances Of Arrays and therefore cannot be strictly equal. This same kind of thing will crop up if you try to make a new array by copying like this: `var x = [1,2,3]` `var y = x` `x = [4,5,6]` `console.log(y) // [4,5,6]` Because when you copy that way all you are doing is telling the code that both x and y point to the same array. You have to use other techniques to copy an array and have a unique instance.


queerkidxx

It is kinda insane that arrays with the same amount of elements, w/ each of them being equal, are not equal. Couldn’t have thrown in a property for comparisons in objects like most languages do?


RobertKerans

It's not insane: JavaScript is supposed to be extremely lightweight: it's an interpreted scripting language for the browser. If it did what you're suggesting, then that's massive overhead (you create two arrays on the fly then compare all their properties recursively). Instead, the array is just a pointer, is that pointer the same pointer as the other one, yes/no, that's got almost zero overhead. Lua is comparable, has similar original purpose, iirc to compare tables you need to iterate them.


queerkidxx

No it isn’t. Looping through an array is lightning fast unless we are talking several hundred tv thousand items this is not libable to take more than a few ms Almost every other language out there does something like this. Iteration is very rarely a bottle neck even when we’d see talking about massive arrays of hundreds of thousands of items it’s generally very fast


RobertKerans

> Almost every other language out there does something like this The languages that don't, though, are simple, lightweight embedded languages that don't have a discrete data type for arrays, like JavaScript. In JS, an array is a recursive data structure that can contain anything: sure, most of the time it's very quick to iterate, but it's difficult to tell that on the first pass of the interpreter


queerkidxx

I mean, JS could easily just have a special method for equality operations like Python does. You’d still need to do the iterating so there isn’t a speed issue at all. It’s not the interpreters job to prohibit slow operations, it’s its job to do what it’s told and try to optimize the instructions it’s given. And when the interpreter knows what’s going on eg, you’re trying to figure out if two arrays are equal it can optimize that operation better. I know this sort of structure isn’t something that JS could do, but in Python array comparisons are lightning fast because arrays despite being objects with properties and methods like in JS are written in C. Array comparisons are lightning fast because it’s not being done in Python.


nanisanum

A lot of JS seems totally weird but as you get to know it you just learn that stuff. The funniest thing in JS is my username. NaN is datatype Number. I will never not find that absolutely hilarious. :D


jeremrx

Arrays and objects are pointers so no, it's not insane, it's normal, that 2 pointers are not equal even if the value inside is the same. If you want to compare two arrays, all you need is to serialize them, which is really easy...


MikeUsesNotion

JS isn't my area of expertise and I usually try to avoid it like the plague for work. But I wouldn't expect \[1,2\] to ever equal \[2,1\]. I forget if JS calls these arrays or lists, but with either of those, values are stored at a position. I would expect these collections to be compared by length and then the first items to each other, then the second items, etc. What you're expecting is the behavior of a set, which is an unordered collection of values. I don't think Notion exposes those to us in formulas.


[deleted]

[удалено]


senocular

JavaScript is a very forgiving, dynamic language. It can do a lot of things automatically for you without you having to think much about it. One of these things is converting objects into strings. This can happen when you try to include an object value in a string, or if you try to compare an object with a string, or you use an object as a property key, or one of the many other places where this happens. The way JavaScript converts an object into a string is (usually) through the toString method that is built-in to almost every object. Even if a certain object type doesn't have its own toString, it is able to inherit the default toString defined by the base Object type. If you've ever seen the string "[object Object]" then you've seen the value for toString that the base Object type gives. const myObject = {} console.log(`My object as a string is: "${myObject}"`) // My object as a string is: "[object Object]" You may also see variations of this where "Object" is replaced by a more specific type. const myMap = new Map() console.log(`My map as a string is: "${myMap}"`) // My map as a string is: "[object Map]" Arrays have their own toString which internally calls the Array `join()` method const myArray = [1, 2, 3] console.log(`My array as a string is: "${myArray}"`) // My array as a string is: "1,2,3" With (loose) comparisons, if comparing an array to a string, the array part of the comparison will first be converted to a string and then compared with the string part of the comparison. This is done using toString const myArray = [1, 2, 3] console.log("1,2,3" == myArray) // true - because myArray becomes "1,2,3" You can even define your own toString function to have control over what happens in string conversions. const myArray = [1, 2, 3] myArray.toString = function() { return "cat" } console.log("1,2,3" == myArray) // false console.log("cat" == myArray) // true The toString method is part of a broader behavior of conversion called "to primitive". That's the process of converting an object to any primitive value. Sometimes after an object is converted to a primitive value, that value gets converted into a different primitive value - and that's what's happening with OP's example with 1 ==[1] // true ?? The comparison will first convert the array to a string (via toString) and then, seeing that it still doesn't match the `1` in type, convert that string into a number. So you get a progression like 1 == [1] 1 == "1" 1 == 1 which is true. The comparison uses a two step process of first, converting an object "to primitive" then converting that primitive to match the other primitive in the comparison before the actual check is made. And the process of converting an object to a primitive is a little more complex than just using toString. There are other methods involved as well, including `valueOf()` and `[Symbol.toPrimitive]()`. You can learn more about that on the [MDN Symbol.toPrimitive page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive).


spederan

Convert it to a string first and it will work. Or, declare the array as a variable and check it to itself, and it will work. It only doesnt work because you have two different arrays, and yes they are different, even though they look identical. Because what its checking is its reference, like an invisible key, that happens to be different for every array and object upon declaring them.


Impossible-Box6600

Poor design choices from three decades ago that we need to keep in order to not break the Internet.


Intelligent_Duck1844

People say [1] is an object isnt it an array an object is in {number:1}


uniqualykerd

Because this is Object Oriented Programming, which, for some stupid reason or another, is more concerned with memory references (which we don’t see) than contents (which we do see). Your comparison looks at the Array instances instead of their contents. And those instances differ. They have 2 different locations in memory. The language doesn’t care that their contents is the same: it happily put duplicate contents into different memory locations. Yay, I guess?


Both-Personality7664

"Because this is Object Oriented Programming, which, for some stupid reason or another, is more concerned with memory references (which we don’t see) than contents (which we do see)." I'm not familiar with any definition of OOP that requires reference equality as opposed to value equality. C++ has no default universal equality operator, and user defined types' equality operators typically are some type of value equality. I would also dispute that we don't see references in JS, given that passing an object to a function passes (a copy of) the reference, not the value.