Comparing primitives
Primitives are stored by value, so checking them for equality is simple. We use the ==
operator.
const firstInt = 42;
const secondInt = 86;
// Can also use === since types are the same
if (firstInt == secondInt) {
console.log("These are equal.");
} else {
console.log("These are not equal.");
}
Comparing objects
Variables that hold objects are called reference types
, because they hold a reference to an object. Think of this as a pointer to the object stored as a memory address.
If we compare two object reference using the equals (==
|| ===
) operator, we are actually comparing the references, not the values to which they refer.
Try this. You may be surprised:
const firstNum = new Number(42);
const secondNum = new Number(42);
// === does the same
if (firstInt == secondInt) {
console.log("These are equal.");
} else {
console.log("These are not equal.");
}
What just happened?
I am me
Try changing secondInt
to firstInt
in the comparison. What happens?
const firstNum = new Number(42);
const secondNum = new Number(42);
// === does the same
if (firstInt == firstInt) {
console.log("These are equal.");
} else {
console.log("These are not equal.");
}
Doing it right
If we need to compare equality of Object
s, we unfortunately do not have a built in way to do so in JS. We would have to build this functionality out ourselves. Something like this:
function isEquivalent(a, b) {
const aProps = Object.getOwnPropertyNames(a);
const bProps = Object.getOwnPropertyNames(b);
if (aProps.length != bProps.length) {
return false;
}
for (let i = 0; i < aProps.length; i++) {
const propName = aProps[i];
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
What. Just. Happened???
There is a lot of new code there, but fear not. It's not so bad.
Let's start with the first two lines:
const aProps = Object.getOwnPropertyNames(a);
const bProps = Object.getOwnPropertyNames(b);
All this is doing is assigning the keys in the Object
to an array so we're only observing a single dimension of the Object
at a time.
Next, the first conditional:
if (aProps.length != bProps.length) {
return false;
}
This one is pretty straight forward. We're just checking to see if each object has the same number of values in it. If they don't, these things can't possibly be equal, so the function returns false and sends us on our way.
On the other hand, if the length of the values are indeed the same, now we can dig deeper:
for (let i = 0; i < aProps.length; i++) {
const propName = aProps[i];
if (a[propName] !== b[propName]) {
return false;
}
}
This loop is now going to go through each value in both objects and compare them. If indeed all of the keys exist and contain the same values, we move on past the loop. If, however, any keys mismatch, or values aren't equal, we again return false and keep moving.
Last but not least, if we have gotten through all of those checks, we return true saying that these objects are indeed equal. can you think of a time when we might get a false negative though?
Nested Objects?!?! Come on...
That's right. What if one of the values in the Object is itself an Object? Well we would fail again. (Barring if both Objects are referencing the same Object) This is where things get a bit tricky. We would have to make our equality checker way more complex to check for what's known as Deep Equality.
Now I do my best to avoid libraries and write my own code as much as possible. (as should you) But this is one example where I would use a library like Lo-Dash for this. Using this library, we can import just the method we need to avoid bloating our application and freeing us up from writing this ourselves:
const { isEqual } = require("lodash");
const objOne = { a: 1, b: { c: 2 } };
const objTwo = { a: 1, b: { c: 2 } };
console.log(objOne == objTwo);
console.log(isEqual(objOne, objTwo));
Full circle
Fire up VSCode, and create this Circle
class:
public class Circle {
constructor(radius) {
this.radius = radius;
}
circumference() {
return 2 * Math.PI * radius;
}
}
Note: Math.PI
above is a constant. What does that mean?
Circles of a size
As per our Number
example, this code won't work as you may expect:
const firstCircle = new Circle(42);
const secondCircle = new Circle(42);
if (firstCircle == secondCircle) {
console.log("These are the same size");
} else {
console.log("These aren't the same size.");
}
Again, time to invest in something like Lodash...