JavaScript

In JavaScript, how do we compare two variables for equality?

a == b

So, what would the following code output?

1
2
3
let apple = [1, 2];
let banana = [1, 2];
console.log(apple == banana);

It’s surprisingly false! You might exclaim, “How is that possible? They are clearly identical!”

Actually, the JavaScript documentation explains the usage of == (loose equality). JavaScript first checks if the variables on both sides have the same type; if they do, it proceeds with further comparison. If both variables are of type object (which includes arrays in JS), JavaScript checks if these two variables point to the same object.

Let’s look back at let apple = [1, 2]. Just as it is expressed: “Define an array, and its name is ‘apple’.” This array could be allocated anywhere in the system’s memory. apple is merely a variable that holds the memory address (reference) where the array is stored—nothing more. Therefore, when we define apple = [1, 2]; and banana = [1, 2];, one array is stored at some memory location found through apple, and another distinct array is stored at some other memory location found through banana. Although these two arrays have the same elements, they are two different arrays stored in different parts of memory. During strict (and even this loose comparison for objects), they are not the same identity, so the result is false.

Let’s examine another comparison:

1
2
3
4
let apple = {"name": "Alice"};
let banana = apple;
apple = {"name": "Alice"};
console.log(apple == banana); // false

Guess what happened? Why is it false?

We defined an object literal (acting like a hash) and had the variable apple point to it. We then defined variable banana and set it equal to apple, so banana now points to the exact same object that apple was pointing to. Now, we define a new, absolutely identical-looking object, and reassigned apple to point to it. Thus, the data apple and banana point to are two identical-content objects in different memory locations. Although they look the same, they are not the same identity object.

Two distinct objects are never equal for either strict or abstract comparisons.

Let’s see if Python and Ruby have this same issue.

Ruby

Ruby has several comparison methods. One method is equal?(). This method is defined by BasicObject (the parent class of all other classes).

1
2
3
4
5
6
7
a = [1, 2, 3]
b = [1, 2, 3]
c = a
p [1, 2, 3] == [1, 2, 3] # true (structural equality)
p [1, 2, 3].equal?([1, 2, 3]) # false (identity equality)
p a.equal?(b) # false
p a.equal?(c) # true

When we use == to compare two arrays in Ruby, it performs a structural comparison: it compares elements one by one. Two arrays are equal only if every element is equal and in the same position within the array. However, when we use the equal? function to compare two arrays, it returns true only if they refer to the exact same object identity.

Furthermore, Ruby provides the eql? method for a more rigorous comparison than ==. It compares the hash values of two objects; they are only equal if their hash values are equal. Most comparable objects in Ruby have a .hash method, which returns the hash value used by eql? for testing equality.

Python

In Python, is is used to determine if two variables point to the same object. For example:

1
2
3
4
5
6
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True (value equality)
print(a is b) # False (identity equality)
print(a is c) # True

Similar to identity checks in JS/Ruby, if the two compared objects do not refer to the same instance, is returns False.

Conclusion

JavaScript’s == has a quirk: it doesn’t give us direct value comparison for two complex object types. Instead, for primitive types, it may perform type coercion and then strict comparison. Strict comparison for objects specifically means checking whether both references point to the exact same object instance. When we say object, we are referring specifically to JavaScript’s Object type.