3

I'm dealing with a strange situation with Javascript,

I know that the strange moments of JS (like this) are not strange at all, simply the code working completely predictably and exactly as specified.

var materials_1 = ['Hydrogen', 'Helium', 'Lithium'];
var materials_2 = ['Hydrogen', 'Helium', 'Lithium'];
var materials_3 = "Hydrogen,Helium,Lithium";

console.log(materials_1 == materials_3); //True
console.log(materials_2 == materials_3); //True
console.log(materials_1 == materials_2); //False

console.log([] == []);  //False

But, can someone provide me a detailed explanation when using == in this kind of equality comparaison ?

Thank you for your light.

NB: I have checked How to compare arrays in JavaScript?, this question does not treat the comparison case with a string !

L Y E S - C H I O U K H
  • 4,765
  • 8
  • 40
  • 57
  • Also [Which equals operator (== vs ===) should be used in JavaScript comparisons?](https://stackoverflow.com/questions/359494/which-equals-operator-vs-should-be-used-in-javascript-comparisons) – Mohammad Usman May 06 '18 at 12:34
  • 1
    @MohammadUsman, i have checked this questions ! My question is more oriented object-string and no comparison operator! – L Y E S - C H I O U K H May 06 '18 at 12:36
  • https://stackoverflow.com/questions/7314635/why-isnt-1-2-3-equal-to-itself-in-javascript – Bergi May 06 '18 at 12:48

3 Answers3

2

The == operator means equality with conversion.

When used with two different types, one (or both) will be coerced to a common type for the comparison to be performed. That's what's happening with the first two test cases (array == string).

From MDN:

Equality (==)

The equality operator converts the operands if they are not of the same type, then applies strict comparison. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

So, when two objects are compared (arrays are objects), they are already of the same type, so the object reference is compared against the other. With objects, it's not the data that is being compared, it's the actual object in memory, so the two variables are compared to see if they point to the same memory location, which, in your case, they don't.

Community
  • 1
  • 1
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

Even if materials_1 and materials_2 contain the same string values, they are actually two different Arrays. When you compare them, you are actually comparing references, that's why something like that will always be false, regardless of the content of the Arrays.

The same applies for [] == []. Each [] creates a new empty array and then you compare the references to them.

However, when you compare them to materials_3, which is a string (using ==), JS will call valueOf() on the other arrays to convert them to their primitive value. As the value returned from valueOf() is not a primitive either, it will call toString() on it, which returns "Hydrogen,Helium,Lithium". As strings are primitives, now the comparison will be done by value and return true.

You can find more about valueOf() on MDN:

JavaScript calls the valueOf method to convert an object to a primitive value. You rarely need to invoke the valueOfmethod yourself; JavaScript automatically invokes it when encountering an object where a primitive value is expected.

By default, the valueOfmethod is inherited by every object descended from Object. Every built-in core object overrides this method to return an appropriate value. If an object has no primitive value, valueOfreturns the object itself.

You can see that in action here:

function ObjectWrapper(actualObject) {
  this.actualObject = actualObject || {};
}

ObjectWrapper.prototype.valueOf = function() {
  console.log('valueOf');
  
  return this.actualObject; // Not a primitive.
};

ObjectWrapper.prototype.toString = function() {
  console.log('toString');
  
  return this.actualObject.toString();
};

const foo = new ObjectWrapper([1, 2, 3]);
const bar = '1,2,3';

console.log(foo == bar);
Community
  • 1
  • 1
Danziger
  • 19,628
  • 4
  • 53
  • 83
0

Javascript tries to convert both the variables under comparison to same similar types when == operator is used and at least one of the operand is primitive. Reference

So in your case,

Case 1 : materials_1 == materials_3 is processed as materials_1.toString() == materials_3 (Which turns out to be true)

Case 2 : Same as that of case 1

Case 3 : Here both the operands are of same type (i.e. Array). As Objects are compared based on references, they would obviously have different memory location and hence they will not be equal.

Deva Gerald
  • 284
  • 2
  • 6