Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active Sep 22, 2022
Embed
What would you like to do?
strictEquals.js
// Your scientists were so preoccupied
// with whether or not they could,
// they didn't stop to think if they should.
// Like a === b
function strictEquals(a, b) {
if (Object.is(a, b)) {
// Same value.
// Is this NaN?
if (Object.is(a, NaN)) { // We already know a and b are the same, so it's enough to check a.
// Special case #1.
return false;
} else {
// They are equal!
return true;
}
} else {
// Different value.
// Are these 0 and -0?
if (
(Object.is(a, 0) && Object.is(b, -0)) ||
(Object.is(a, -0) && Object.is(b, 0))
) {
// Special case #2.
return true;
} else {
// They are not equal!
return false;
}
}
}
@kvnam
Copy link

kvnam commented Sep 17, 2021

Any inputs on what I'm missing would be appreciated

function strictEquals(a, b){
  const specialCases = [0, -0];
  if(Number.isNaN(a) && Number.isNaN(b)){
    return false;
  }
  if(!specialCases.includes(a) || !specialCases.includes(b)){
    return Object.is(a, b);
  }
  return true; // Only in case of 0 === -0 or -0 === 0
}

@aaronmbos
Copy link

aaronmbos commented Sep 20, 2021

const strictEquals = (a, b) => {
    if (Object.is(a, NaN) && Object.is(b, NaN))
        return !Object.is(a, b);
    if ((Object.is(a, -0) && Object.is(b, 0)) || (Object.is(b, -0) && Object.is(a, 0)))
        return !Object.is(a, b);

    return Object.is(a, b);
};

@SergioAVelasco
Copy link

SergioAVelasco commented Sep 20, 2021

Any inputs on what I'm missing would be appreciated

function strictEquals(a, b){
  const specialCases = [0, -0];
  if(Number.isNaN(a) && Number.isNaN(b)){
    return false;
  }
  if(!specialCases.includes(a) && !specialCases.includes(b)){
    return Object.is(a, b);
  }
  return true; // Only in case of 0 === -0 or -0 === 0
}

Your second if is wrong, what about the case of having 0, and 2 as inputs, to enter on the second if both values has to not be on the special cases, but as 0 is on special case array it will return true. every input no zero passed with zero value with return wrongly a true value

@kvnam
Copy link

kvnam commented Sep 20, 2021

Any inputs on what I'm missing would be appreciated

function strictEquals(a, b){
  const specialCases = [0, -0];
  if(Number.isNaN(a) && Number.isNaN(b)){
    return false;
  }
  if(!specialCases.includes(a) && !specialCases.includes(b)){
    return Object.is(a, b);
  }
  return true; // Only in case of 0 === -0 or -0 === 0
}

Your second if is wrong, what about the case of having 0, and 2 as inputs, to enter on the second if both values has to not be on the special cases, but as 0 is on special case array it will return true. every input no zero passed with zero value with return wrongly a true value

Thank you @SergioAVelasco! You are right, I completely missed that one 🤦 I updated it to check if either of the two is not a special case (0 / -0) use Object is. if(!specialCases.includes(a) || !specialCases.includes(b)){
So we only pass this if if both are in special case, which works even if they are equal, so it would return true for
0,0
-0, -0
0, -0
Please let me know if you spot any cases I've missed with this one.

@josileudo
Copy link

josileudo commented Oct 5, 2021

function strictEquals(a,b) {
  if (Object.is(a , b)) {
    if (Object.is(a , NaN)){
      return false
    }
    return true
  } else {
    if (
        (Object.is(a , 0) && Object.is(b , -0)) || 
        (Object.is(a, -0) && Object.is(b , 0))
      ) {
      return true
    }
    return false
  }
}

const result = strictEquals(-0 , 0)
console.log(result)

@wfercanas
Copy link

wfercanas commented Oct 16, 2021

Although I see a lot of answers! I want to share mine:

var strictEquals = (a, b) => {
  // I prefer to start with the exceptions

  //Checking for NaNs
  if (Number.isNaN(a) && Number.isNaN(b)) {
    return false;
  }
  
  // evaluate to true when parameters are 0 and -0 disregarding the order.
    if (!a && !b && !-a &!-b) {
    return true;
  }

  // a plain Object.is for everything else
    return Object.is(a,b);
}

@Makeem49
Copy link

Makeem49 commented Oct 25, 2021

I checked for the two special cases where Object.is() behave differently from strict equal ===

function strictEqual(a,b) { 
  if(Object.is(a, NaN) && Object.is(b, NaN)) {
    return false
  } else if (Object.is(a, 0) && Object.is(b , -0) || Object.is(a, -0) && Object.is(b, 0)) {
    return true
  } else {
    if (Object.is(a,b)) {
      return true
    } else {
      return false 
    }
  }
}

@fResult
Copy link

fResult commented Nov 20, 2021

My solution is

function strictEqual(a: unknown, b: unknown) {
  if (Object.is(a, NaN)) return false
  return new Set([a]).has(b)
}

@ivano-vvv
Copy link

ivano-vvv commented Nov 24, 2021

function strictEquals(a, b) {
    if (Number.isNaN(a) || Number.isNaN(b)) {
        return false;
    }

    if (Object.is(a, -0) || Object.is(b, -0)) {
        return strictEquals(Math.abs(a), Math.abs(b));
    }

    return Object.is(a, b);
}

@lhendriks1
Copy link

lhendriks1 commented Jan 1, 2022

Here's my attempt, seems to pass all cases! This should be turned into a code katas question haha

const strictEquals = (a, b) => {
   const objectIs = Object.is(a, b);

   if (objectIs) {
     if (isNaN(a)) {
       return false
     } else return true;
   }

   if (typeof a === 'number' && typeof b === 'number') {
     if (isNaN(a/b)) {
       return true;
     }
   }
   return false;
 }

@jspthesixth
Copy link

jspthesixth commented Jan 6, 2022

function strictEquals(a, b) {
  if (Object.is(NaN, b)) return false

  if (
    (Object.is(a, 0) && Object.is(b, -0)) ||
    (Object.is(a, -0) && Object.is(b, 0))
  )
    return true

  if (Object.is(a, b)) return true

  return false
}

@JESii
Copy link

JESii commented Jan 11, 2022

const strictEqual = (a, b) => {
if (a != a || b != b) return false; // NaN
const aa = typeof a == "number" ? a + 0 : a; // -0
const bb = typeof b == "number" ? b + 0 : b; // -0
return Object.is(aa, bb);
};

// Following is some test code
const testDisplay = (a, b) => {
const sEql = strictEqual(a, b);
const jEql = a === b;
console.log(a, b, sEql, jEql, sEql !== jEql ? "==========> ERROR!!!" : "OK");
};

const testSet1 = [
null,
undefined,
NaN,
-0,
0,
true,
false,
5,
"5",
15,
17,
"string",
"anotherstring",
{},
[],
1.5,
1.75,
];

console.log(Starting tests with input = ${JSON.stringify(testSet1)});
console.log("NOTE: first three values are null, undefined, NaN");
console.log("Symbols and BigInts not included in the tests");

for (let i = 0; i < testSet1.length; i++) {
for (let j = 0; j < testSet1.length; j++) {
testDisplay(testSet1[i], testSet1[j]);
}
}

@eqaderi
Copy link

eqaderi commented Jan 15, 2022

function strictEquals(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false;
  }

  if (
    Object.is(Math.abs(a), 0) &&
    Object.is(Math.abs(b), 0) &&
    !Object.is(a, b)
  ) {
    return true;
  }

  return Object.is(a, b);
}

@kumarsandeep91
Copy link

kumarsandeep91 commented Jan 16, 2022

function strictEquals(a,b) {
    if (Object.is(a, NaN) && Object.is(b, NaN)) {
        return false;
    }

    if ((Object.is(a, 0) || Object.is(a, -0)) && (Object.is(b, 0) || Object.is(b, -0))) {
        return true;
    }

    return Object.is(a,b)
}

@joespinelli7
Copy link

joespinelli7 commented Jan 17, 2022

Hey all!
Would this work?

function strictEquals(a, b) {
  if (!Object.is(typeof(a), typeof(b))) {
    return false;
  }

  if (Number.isNaN(a) && Number.isNaN(b)) {
    return false;
  }

  if ((a + '').includes(0) && (b + '').includes(0)) {
    if ((Math.abs(a) + '').length < 2 && (Math.abs(b) + '').length < 2) {
      return true;
    }
  }

  return Object.is(a, b);
}

@ooade
Copy link

ooade commented Jan 26, 2022

const strictEquals = (a, b) => {
  if (Number.isNaN(a) && Number.isNaN(b)) return false;
  
  if (Object.is(a, -0)) {
    a = 0;
  }
  
  if (Object.is(b, -0)) {
    b = 0;
  }
  
  return Object.is(a, b);
};

@sudongyuer
Copy link

sudongyuer commented Feb 1, 2022

My answer 🐥

function strictEquals(a, b) {
    if (Object.is(a, b)) {
        if (Object.is(a, NaN) || Object.is(b, NaN)) {
            return false
        } else {
            return true
        }
    } else {
        if ((Object.is(a, -0) && Object.is(b, 0)) ||
            Object.is(b, -0) && Object.is(a, 0)) {
            return true
        } else {
            return false
        }
    }

}

@allamasln
Copy link

allamasln commented Feb 8, 2022

function strictEquals(a, b) {
    if (Number.isNaN(a) || Number.isNaN(b)) {
        return false;
    }
    else if ((Object.is(a, -0) && Object.is(b, 0)) || 
	     (Object.is(a, 0) && Object.is(b, -0))) {
        return true;
    }
    else {
        return Object.is(a,b);
    }
}

@ifndefdeadmau5
Copy link

ifndefdeadmau5 commented Feb 12, 2022

am I missing something?

function strictEquals(a,b) {
    // consider below 2 special cases
    // -0, 0
    // NaN NaN
    if (Object.is(a, NaN) && Object.is(b, NaN)) return false;
    if (Object.is(a, 0) && Object.is(b, -0)) return true;

 return Object.is(a, b);
}

@TiesNoordhuisBITAcademy
function strictEquals(param1, param2) {
    if (Number.isNaN(param1) && Number.isNaN(param2)) {
        return false;
    }
    if (Object.is(param1, -param2) && Object.is(Math.abs(param1), 0)) {
        return true;
    }
    return Object.is(param1, param2)
}

@gilsonnunesfilho
Copy link

gilsonnunesfilho commented Feb 17, 2022

I'd prefer to use a more readable approach, but for sake of studying, I tried this alternative as a single line:

const strictEquals = (a, b) => Object.is(a + 1, b + 1) && !Object.is(a, NaN)

@shreenath-is
Copy link

shreenath-is commented Feb 20, 2022

Here is what where my brain went to.

function strictEquality(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false;
  }

  let isANumber, isBNumber;

  isANumber = Object.is(typeof a, "number");
  isBNumber = Object.is(typeof b, "number");

  if (isANumber && isBNumber && Number.isNaN(a / a) && Number.isNaN(b / b)) {
    return true;
  }

  return Object.is(a, b);
}

@torsak
Copy link

torsak commented Feb 26, 2022

const strictEquals = (a, b) => {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    return false
  } else if (Object.is(a, 0) && Object.is(b, -0)) {
    return true
  } else if (Object.is(a, -0) && Object.is(b, 0)) {
    return true
  }

  return Object.is(a, b)
}

Tests

const assert = (a, b, expect) => {
  if (strictEquals(a, b) !== expect) {
     console.log(`Failed: ${a}, ${b}`)
  }
}

assert(NaN, NaN, false)

assert(-0, 0, true)
assert(0, -0, true)
assert(-0, -0, true)
assert(0, 0, true)

assert(Infinity, Infinity, true)
assert(Infinity, -Infinity, false)
assert(-Infinity, Infinity, false)

assert(null, null, true)
assert(undefined, undefined, true)

assert(1, 1, true)
assert("NaN", "NaN", true)
assert({}, {}, false)
assert([], [], false)

const obj1 = {}
const obj2 = obj1
assert(obj1, obj2, true)

const nancy = 0 / 0
assert(nancy, NaN, false)

@jackliDev
Copy link

jackliDev commented Mar 16, 2022

The question stated we couldn't use strict equality but didn't forbid loose equality so I used that:

function strictEquals(a, b) {
    if (Number.isNaN(a) && Number.isNaN(b)) {
        return false;
    }

    // 0/0, -0/0. 0/-0, -0/-0 cases
    if (typeof a == 'number' && typeof b == 'number' && Number.isNaN(a/b)) {
        return true;
    }

    return Object.is(a, b);
}

@whylost
Copy link

whylost commented Mar 31, 2022

 const strictEquals = (a, b) => {
        const equal = Object.is
        const isNumber = num => equal(typeof(num),'number')
        
        // Special Case: -0 +0  & Special Case: NaN
        if(isNumber(a) && isNumber(b)){
            return (equal(a,b) || equal(a+1,b+1)) && !equal(a,NaN) && !equal(b,NaN)
        }

        return equal(a,b)
    }
const strictEquals = (a, b) => {
            const equal = Object.is

            // Same value
            if (equal(a, b)) {
                // Special Case: NaN --> We already know a and b are the same, so it's enough to check a.
                if (equal(a, NaN)) {
                    return false
                }
                return true
            }else{
                // Special Case: -0 +0
               if (
                    (equal(a, 0) && equal(b, -0)) ||
                     (equal(a, -0) && equal(b, 0))
                ) {
                    return true
                }
                return false
            }

        }

@PhilippK13
Copy link

PhilippK13 commented Apr 2, 2022

function strictEquals(a, b){
  return (Object.is(a, NaN) && Object.is(b, NaN))
            ? false
            : (
                (Object.is(a, 0) && Object.is(b, -0)) ||
                (Object.is(a, -0) && Object.is(b, 0))
              )
              ? true
              : Object.is(a, b);
}

@krzysztof-kozak
Copy link

krzysztof-kozak commented Apr 16, 2022

I see folks are posting their solutions, so I will post mine too, just for fun :P

function strictEquals(a, b) {
  if (Object.is(a, NaN) || Object.is(b, NaN)) {
    return false;
  }

  if (Object.is(a, 0) && Object.is(b, -0)) {
    return true;
  }

  if (Object.is(a, -0) && Object.is(b, 0)) {
    return true;
  }

  return Object.is(a, b);
}

@trevithj
Copy link

trevithj commented May 10, 2022

I thought I'd share my 'aha' moment.
My first condition was:

  if(isNaN(a) && isNaN(b)) return false;

Which seemed to work just fine, until I tried strictEquals(strictEquals,strictEquals) just for fun. Result: false.

So I learned the following fun fact:

 isNaN(strictEquals);        //true
 Number.isNaN(strictEquals); //false

When in doubt, read the docs!. That coercion can be a real Yml0Y2g=.

@rohit1101
Copy link

rohit1101 commented Aug 6, 2022

function strictEqual(a, b) {
  if (Object.is(a, b)) {
    if (Object.is(a, NaN)) {
      return false;
    }
    return true;
  }
  if (!Object.is(a, b)) {
    if (Object.is(a, 0) && Object.is(b, -0)) {
      return true;
    }
    if (Object.is(a, -0) && Object.is(b, 0)) {
      return true;
    }
    return false;
  }
}

console.log(strictEqual(NaN, NaN));

@elTallarin
Copy link

elTallarin commented Aug 26, 2022

function stringEquals(a, b) {
    if (isNaN(a)) return false
    if ([0, -0].includes(a) && Object.is(a, -b)) return true
    return Object.is(a, b)
}

First special case NaN === NaN => both a and b will be NaN and therefore, and if either value is NaN, should return false. Other case, return the result of Objects.is(a, b)

Second sepecial case 0 === -0 or -0 === 0 => if the a is 0 or -0 and Object.is(a -b), its one of the special situations, that needs to return true. Otherwise, return Object.is(a, b)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment