Javascript Interview Question: Implement abstract equality algorithm
Difference between == and ===, that you don’t know yet
If we ask the difference between == and ===, the majority of people will say that == does loosely type checking whereas === does type + value checking.
Which is not the whole truth.
This is completely wrong.
== or Abstract equality also does the type checking in fact, type checking is the first thing that == does.
So what is the difference between == (Abstract Equality) and === (Strict Equality)?
Let’s find out together.
== (Abstract Equality) does 4 special things, if we are comparing two variables x
and y
.
1. Check the type of both variables.
if the type of x
and type of y
is the same, then do a strict equality check and return the result.
1 == 1;
Internally return 1 === 1
2. Check for null and undefined
If x
is null and y
is undefined, return true
If x
us undefined and y
is null, return true
null == undefined; // true
undefined == null; // true
3. ToPrimitive Conversion of non-primitives
if we compare non-primitives like Object and arrays, == (Abstract Equality) first convert them to their non-primitive equivalent by calling toString()
method.
[] == ""; // [ ] will be converted into string
[].toString() == "";
"" == ""; // true
4. Convert to Number (== loves Number)
If x
is of type Number, then convert y
to Number by wrapping y
in a Number function call, and then compare the result.
If y
is of type Number, then convert x
to Number by wrapping x
in a Number function call, and then compare the result.
"1" == 1; // "1" will be converted into Number
Number("1") == 1
1 == 1 // true
So by seeing the above steps we can conclude that, == (Abstract Equality) does the type coercion while comparing variables, whereas ===(Strict Eqaulity) does not do any kind of type coercion.
And this is the real difference between == and ===.
Here is the rough Implementation of the Abstract Equality Algorithm:
function abstractEquality(value1, value2) {
// Step 1: If the types are the same, perform a regular equality check
if (typeof value1 === typeof value2) {
return value1 == value2;
}
// Step 2: If one of the values is null and the other is undefined, they are equal
if ((value1 === null && value2 === undefined) || (value1 === undefined && value2 === null)) {
return true;
}
// Step 3: If one of the values is a number and the other is a string, perform numeric string conversion
if ((typeof value1 === 'number' && typeof value2 !== 'object') ||
(typeof value1 !== 'object' && typeof value2 === 'number')) {
return Number(value1) == Number(value2);
}
// Step 4: If one of the values is an object, perform string conversion
if (isObject(value1) || isObject(value2)) {
return String(value1) == String(value2);
}
// Step 5: In all other cases, the values are not equal
return false;
}
// Helper function to check if a value is an object
function isObject(value) {
return typeof value === 'object' && value !== null;
}
I hope now you will be able to easily solve and reason about popular JS tricky questions like:
// 1
[] == false;
// 2
[1] == 1;
// 3
{} == "";
Here is the office spec link of Abstract Equality in case you want to dig deeper.
https://262.ecma-international.org/5.1/#sec-11.9.3