Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active January 26, 2024 15:13
Show Gist options
  • Save gaearon/08a85a33e3d08f3f2ca25fb17bd9d638 to your computer and use it in GitHub Desktop.
Save gaearon/08a85a33e3d08f3f2ca25fb17bd9d638 to your computer and use it in GitHub Desktop.
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;
}
}
}
@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

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

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

@DanelYu
Copy link

DanelYu 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

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

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)

@dmakwt
Copy link

dmakwt commented Oct 8, 2022

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

    if((a == 0 && b == 0) ||  (a == -0 && b == -0)){
        return true;
    }


    return  Object.is(a,b);
    
}

@ayoub-ahabchane
Copy link

ayoub-ahabchane commented Oct 28, 2022

Coming late to the party:

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

      if (
        typeof a === "number" &&
        typeof b === "number" &&
        Object.is(Math.abs(a), Math.abs(b))
      ) {
        return true;
      }

      return Object.is(a, b);
    }

@sedsawyum
Copy link

sedsawyum commented Nov 19, 2022

function strictEquals(a, b) {
  return typeof a == typeof b && a == b
} 

seems to be working.
And if it valid seems to be good reason to use double equal

@sedsawyum
Copy link

sedsawyum commented Nov 19, 2022

Coming late to the party:

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

      if (
        typeof a === "number" &&
        typeof b === "number" &&
        Object.is(Math.abs(a), Math.abs(b))
      ) {
        return true;
      }

      return Object.is(a, b);
    }

Check exercise requirements then have a look at your code one more time. You will have a smile on your face :-)

@thomsebastin
Copy link

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

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

  return Object.is(a, b);
}

@aldanamichelino
Copy link

aldanamichelino commented Dec 1, 2022

//mine is similar to others, but I wanted to share anyway :)

`function strictEquals(a, b){
if(Object.is(a, b)){
// they're equal
if(Number.isNaN(a) && Number.isNaN(b)){
//if it is Nan, return false
return false;
}

//else they're equal
return true;

} else {
//if both values are either 0 or -0
if((Object.is(a, 0) || Object.is(a, -0))
&& ((Object.is(b, 0) || Object.is(b, -0)))
){
return true;
} else {

  //else they're not equal
  return false;
}

}
}`

@elcontrastador
Copy link

elcontrastador commented Dec 12, 2022

const strictEquals = (a, b) => {
  if ((typeof a).match(/number/) && (typeof b).match(/number/)) {
    if (Object.is(a, NaN)) { return false };
    if (!a && !b) { return true };
  }
  return Object.is(a, b);
}

console.assert(strictEquals(NaN, NaN) === false, "strictEquals(NaN,NaN) should be false");
console.assert(strictEquals(0, -0) === true, "strictEquals(0,-0) should be true");
console.assert(strictEquals(-0, 0) === true, "strictEquals(-0,0) should be true");
console.assert(strictEquals(-0, -0) === true, "strictEquals(-0,-0) should be true");
console.assert(strictEquals("dog", "dog") === true, "strictEquals('dog','dog') should be true");
console.assert(strictEquals("dog", "cat") === false, "strictEquals('dog','cat') should be false");

@Getnett
Copy link

Getnett commented Dec 13, 2022

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

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

     return Object.is(a,b)
    
}

@kevinvu184
Copy link

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

@patorjk
Copy link

patorjk commented Dec 17, 2022

Someone above already posted this idea, but this would work if you wanted a single line version:

const strictEquals = (a, b) => typeof a == typeof b && a == b;

A long time ago I remember reading in JavaScript: The Good Parts that == was the "evil twin" of === and that it worked correctly when the values were of the same type, but things got messy when the values were of different types. The take away for me was that === was == but with a type check. Not sure why that stuck with me all these years.

@ouichniaziz
Copy link

function strictEquals(a, b) {
  if (a === NaN && b === NaN) return !Object.is(a, b);
  if (a === -0 && b === 0) return !Object.is(a, b);
  if (b === -0 && a === 0) return !Object.is(a, b);
  return Object.is(a, b);
}

@tienhoangvo
Copy link

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

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

@tobias-edwards
Copy link

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

Your implementation incorrectly returns false for strictEquals(-0, 0)

@tobias-edwards
Copy link

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

@Kephass
Copy link

Kephass commented Jan 16, 2023

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

@tobias-edwards your implementation won't work for negative-positive check on numbers other than 0. (try -1 === 1)

@tobias-edwards
Copy link

tobias-edwards commented Jan 16, 2023

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

@tobias-edwards your implementation won't work for negative-positive check on numbers other than 0. (try -1 === 1)

Ah yes, you're right! Thanks. I'll leave my wrong solution to preserve chat integrity

@Kephass
Copy link

Kephass commented Jan 19, 2023

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

@Sergio401
Copy link

const strictEqual = (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
 } 
 else {
   return Object.is(a, b)
 }
}

@furkotikoo
Copy link

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

you are not holding the case
if (Object.is(a, -0) && Object.is(b, 0)) return true;

@joasegovia9427
Copy link

Hi, here is my solution::

const myInfinite = 1/0; // = Infinite
const myCero = 0/myInfinite; // = 0

function stringEquals(a: Number, b: Number){
  if(Number.isNaN(a) && Number.isNaN(b))
    return false;

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

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

let a, b;

a=1;
b=1;
stringEquals(a,b);
console.log(a===b);
console.log(Object.is(a,b));

a=1;
b=2;
stringEquals(a,b);
console.log(a===b);
console.log(Object.is(a,b));

a=0;
b=0;
stringEquals(a,b);
console.log(a===b);
console.log(Object.is(a,b));

a=NaN;
b=NaN;
stringEquals(a,b);
console.log(a===b);
console.log("It must be different:: ",Object.is(a,b));

a=0;
b=-0;
stringEquals(a,b);
console.log(a===b);
console.log("It must be different:: ",Object.is(a,b));

a=-0;
b=0;
stringEquals(a,b);
console.log(a===b);
console.log("It must be different:: ",Object.is(a,b));

Screenshot 2023-05-01 at 22 13 50 (2)

@drfrostongithub
Copy link

drfrostongithub commented May 23, 2023

My Function is like this

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

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

Many already made it.

@betomadrazo
Copy link

betomadrazo commented Jun 3, 2023

My version:

function strictEquals(a, b) {
    if (Number.isNaN(a) && Number.isNaN(b)) return !Object.is(a, b);
    if ((Object.is(a, -0) ^ Object.is(b, -0)) && (Object.is(a, 0) ^ Object.is(b, 0))) return !Object.is(a, b);
  return Object.is(a, b);
}

@sergiosrtd
Copy link

Hope this is the shortest

function strictEquals(a,b){
  if(Number.isNaN(a) && Number.isNaN(b)) return false
  if(!Object.is(a,b) && Object.is(a+"",b+"")) return true
  return Object.is(a,b)
}

@marnauortega
Copy link

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)

I found it interesting that you managed to shorten if (isNaN(a) && isNaN(b)) return false to if (isNaN(a)) return false. You don't need to check if either value is NaN, you have enough with checking if the first value is NaN, in which case it will definitely evaluate to false. And you don't need to care about the remaining case in which b is NaN while a isn't, because Object.is() will handle it perfectly.

@Yinboan
Copy link

Yinboan commented Aug 30, 2023

 function strictEquals(a,b){
     if(typeof a === 'number' && typeof b === 'number'){
         return a == b   
     }
     return Object.is(a,b)
 }

@spcbfr
Copy link

spcbfr commented Sep 27, 2023

I couldn't figure it out on my own so I looked at your version and tried to minimize (not simplify!) it to the best of my ability

const strictEquals = (a,b) => (Object.is(a,b) 
     ? !Object.is(a, NaN) 
     : (Object.is(a, 0) && Object.is(b, -0)) || (Object.is(a, -0) && Object.is(b, 0)))
}

@mhmdsalahsebai
Copy link

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(b, -0) && Object.is(a, 0)) return true;
    return Object.is(a, b);
}

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