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 !

3

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

Comments

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);

Comments

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.

4 Comments

Javascript tries to convert both the objects under comparison No, objects are not converted only primitives are.
If only primitives are converted, case 1 and 2 under question should not return true - right?
I meant that your statement is not correct when its an object and an object being compared (you wrote both the objects). If it's an object == primitive, then there is only one object.
Oops! My bad. Thanks for correcting me.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.