Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active Oct 21, 2021
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;
}
}
}
@pkrzyw

This comment has been minimized.

Copy link

@pkrzyw pkrzyw commented Feb 19, 2020

will this one work or am I missing something?

const strictEquals = (a, b) => {
  if (Object.is(NaN, a)) {
    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)
}
@karpinski1994

This comment has been minimized.

Copy link

@karpinski1994 karpinski1994 commented Feb 19, 2020

@fshiper I've got the same the code, looks like working fine.
Anyone else ;P?

@gaearon

This comment has been minimized.

Copy link
Owner Author

@gaearon gaearon commented Feb 20, 2020

I think this should work!

@sam-mfb

This comment has been minimized.

Copy link

@sam-mfb sam-mfb commented Feb 20, 2020

How about this:

const strictEqual = (x, y) => {

    if(Object.is(x, y) && Object.is(x, NaN)) return false

    else if (Object.is(x+y, x-y)) return true

    else return Object.is(x,y)
}
@sam-mfb

This comment has been minimized.

Copy link

@sam-mfb sam-mfb commented Feb 20, 2020

nevermind; this fails my attempt: strictEqual(undefined, null)

so much for trying to be clever....

@nakhodkin

This comment has been minimized.

Copy link

@nakhodkin nakhodkin commented Feb 20, 2020

Hello @gaearon
How about not using Object.is?

'use strict';

function strictEquals(a, b) {
  return !new Set().add(a).has(b) || new Set().add(Infinity / a).has(Infinity / b);
}
@pacso

This comment has been minimized.

Copy link

@pacso pacso commented Feb 20, 2020

will this one work or am I missing something?

const strictEquals = (a, b) => {
  if (Object.is(NaN, a)) {
    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)
}

Same code I came up with. Can't find anything wrong with it.

@citygent

This comment has been minimized.

Copy link

@citygent citygent commented Feb 20, 2020

let strictEquals = (a, b) => {
  if (!a && !b) {
    return !(a !== b)
  }
  return Object.is(a, b)
}

I am almost entirely sure I am missing something but everything I have tested checks out.

Ah yes I am missing not being able to use !== πŸ€¦πŸ»β€β™‚οΈ

Longhand it is

let strictEquals = (a, b) => {
  if (!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
  }
  return Object.is(a, b)
}

But maybe this falls down somewhere too πŸ€·β€β™‚οΈ

@Alhxor

This comment has been minimized.

Copy link

@Alhxor Alhxor commented Feb 20, 2020

I believe this works as well

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

This comment has been minimized.

Copy link

@reeddunkle reeddunkle commented Feb 20, 2020

I made some tests for the function: https://repl.it/@reeddunkle/strictEquals-test

Paste your code into index.js and press run. I only test the two exceptions that Dan lists in the lesson, and 1 === 1. Feel free to add more.

I left my solution in mysolution.js for sharing and caring.

@axelavargas

This comment has been minimized.

Copy link

@axelavargas axelavargas commented Feb 20, 2020

I believe this works as well

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

This approach seemed almost perfect, but for this case scenario is failing strictEquals(-0, '0'), should be false

@baryshkov

This comment has been minimized.

Copy link

@baryshkov baryshkov commented Feb 20, 2020

Here's mine version. Looks a bit cluttered though.

const strictEquals = (a, b) => {
  let absA = a;
  let absB = b;
  if (Object.is((typeof a), 'number') && Object.is((typeof b), 'number')) {
    absA = Math.abs(a);
    absB = Math.abs(b);
  }
  const equation = Object.is(absA, absB);
  if (equation && (!Object.is(a, NaN) && !Object.is(absB, NaN)))
    return equation;
  else
    return false;
};```
@mknepprath

This comment has been minimized.

Copy link

@mknepprath mknepprath commented Feb 21, 2020

Thanks @reeddunkle - that was super handy! Here was mine:

function 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
  } else {
    return Object.is(a, b)
  }
}
@Aternus

This comment has been minimized.

Copy link

@Aternus Aternus commented Feb 21, 2020

Complete implementation, including handling of undefined:

// implement a === b without using ===
function strictEquals(a, b) {
	// handle NaN
	if (![a, b].includes(undefined) && isNaN(a) && isNaN(b)) {
		return false;
	}
	// handle -0
	if ([0, -0].includes(a) && [0, -0].includes(b)) {
		return true;
	}
	
	 return Object.is(a, b);
}
@rcy

This comment has been minimized.

Copy link

@rcy rcy commented Feb 21, 2020

This works all cases I tested, and passes with handy repl.it jest page above. Didn't use ===/!== but did use == :)

function strictEquals(a, b) {
  if (typeof a == typeof b) {
    return a == b
  }
  return false
}
@rcy

This comment has been minimized.

Copy link

@rcy rcy commented Feb 21, 2020

which can be golfed down to

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

This comment has been minimized.

Copy link

@pasDamola pasDamola commented Feb 21, 2020

@gaearon, here is my solution

let strictEquals = (a, b) => {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false;
  } else if (a < 1 || b < 1) {
    return true;
  } else {
    return Object.is(a, b);
  }
};

@ekediala

This comment has been minimized.

Copy link

@ekediala ekediala commented Feb 22, 2020

let strictEquals = (a, b) => {
  if (!a && !b) {
    return !(a !== b)
  }
  return Object.is(a, b)
}

I am almost entirely sure I am missing something but everything I have tested checks out.

Ah yes I am missing not being able to use !== πŸ€¦πŸ»β€β™‚οΈ

Longhand it is

let strictEquals = (a, b) => {
  if (!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
  }
  return Object.is(a, b)
}

But maybe this falls down somewhere too πŸ€·β€β™‚οΈ

which can be golfed down to

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

The last function is the same solution I came up with. Worked for all values I tested with including the special cases. Think abstract equality ( == ) knows how to take care of the special cases.

@MarcelloTheArcane

This comment has been minimized.

Copy link

@MarcelloTheArcane MarcelloTheArcane commented Feb 22, 2020

If the only constraint is not to use ===, you can just do this, surely?

strictEquals = (a, b) => !(a !== b)
@borntofrappe

This comment has been minimized.

Copy link

@borntofrappe borntofrappe commented Feb 22, 2020

Hopefully this works:

function strictEquals(a, b) {
  if ([a, b].includes(NaN)) {
    return false;
  }
  if (Object.is(a, b * -1)) {
    return false;
  }
  return Object.is(a, b);
}

Semi-confident about Object.is(a, b * -1) handling (0, -0) and (-0, 0).

I tried to use .includes for both exceptions, but it seems the function has its own quirks with values of zero.

@tacensi

This comment has been minimized.

Copy link

@tacensi tacensi commented Feb 22, 2020

Came up with this:

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

This comment has been minimized.

Copy link

@cjnucette cjnucette commented Feb 22, 2020

I don't know how readable is the check for 0 and -0, but here is mine.

const strictEquals = (a, b)  => {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    return false;
  }
  if (!a && !b) {
    return Object.is(Math.abs(a), Math.abs(b));
  }
    return Object.is(a, b);
}
@ATGardner

This comment has been minimized.

Copy link

@ATGardner ATGardner commented Feb 22, 2020

will this one work or am I missing something?

const strictEquals = (a, b) => {
  if (Object.is(NaN, a)) {
    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)
}

This implementation returns false for strictEquals(NaN, NaN)
I'd change line #3 to return Number.isNaN(b);

@torhector2

This comment has been minimized.

Copy link

@torhector2 torhector2 commented Feb 24, 2020

function strictEquals(a, b) {
    // NaN === NaN -> false
    if (Number.isNaN(a) && Number.isNaN(b)) {
        return false
    }

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

    //normal 
    return Object.is(a, b)
}
@pureliumy

This comment has been minimized.

Copy link

@pureliumy pureliumy commented Feb 24, 2020

function strictEquals(a, b) {
  if (arguments.length <= 1 || Number.isNaN(a) || Number.isNaN(b)) {
    return false
  }
  if (!Math.abs(a) && !Math.abs(b)) {
    return true
  }
  return Object.is(a, b)
}
@pacso

This comment has been minimized.

Copy link

@pacso pacso commented Feb 24, 2020

@gaearon, here is my solution

let strictEquals = (a, b) => {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false;
  } else if (a < 1 || b < 1) {
    return true;
  } else {
    return Object.is(a, b);
  }
};

This is quite broken. For example, if you use it to compare 0.1 with 0.2 it returns true. They're definitely not equal.
In fact, if you use it to compare 0.5 with"giraffe" then it'll also say that they're equal.

Also broken for the 0, -0 case.

@ws333

This comment has been minimized.

Copy link

@ws333 ws333 commented Feb 24, 2020

Here is what I came up with...

// Simulate a === b without using ===/!==/==/!=
function strictEquals(a, b) {
  if (Object.is(Math.abs(a),0) && Object.is(Math.abs(b),0)) return true;
  if (Object.is(a, NaN) || Object.is(b, NaN)) return false;
  return Object.is(a, b)
}

Edit:
Ooops, broken for -0 === "0" (Math.abs coerse strings to numbers)
Fixed version with additional updates inspired by other suggestions here.
Thanks for the jest test @reeddunkle!

const strictEquals = (a, b) => {
  const is = Object.is.bind(Object);
  if (!is(typeof a, typeof b)) return false;
  if (is(Math.abs(a),0) && is(Math.abs(b),0)) return true;
  if (is(a, NaN) || is(b, NaN)) return false;
  return is(a, b)
}
@akatopo

This comment has been minimized.

Copy link

@akatopo akatopo commented Feb 25, 2020

Here's one:

function strictEquals(a, b) {
  if (Number.isNaN(a)) {
    return false;
  }
  a = Object.is(a, -0) ? 0 : a;
  b = Object.is(b, -0) ? 0 : b;

  return Object.is(a, b);
}

And another one using Number.isFinite because why not:

function strictEquals(a, b) {
  if (Number.isNaN(a)) {
    return false;
  }
  // -0 + 0 β†’ 0 (but 0 - 0 β†’ 0)
  a = Number.isFinite(a) ? a + 0 : a;
  b = Number.isFinite(b) ? b + 0 : b;

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

This comment has been minimized.

Copy link

@shreyansqt shreyansqt commented Feb 25, 2020

Here's what I did

const 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)) {
        return true;
    }
    return Object.is(a, b);
}
@mchlsm

This comment has been minimized.

Copy link

@mchlsm mchlsm commented Feb 25, 2020

Here's my version:

function strictEquals(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false;
  } else if (Object.is(a, -0) || Object.is(-0, b)) {
    return Object.is(Math.abs(a), Math.abs(b));
  } else {
    return Object.is(a, b);
  }
}
@pkro

This comment has been minimized.

Copy link

@pkro pkro commented Feb 26, 2020

And mine while we're at it, seems to work:

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

	return Object.is((Object.is(a, -0) ? 0 : a),
			 (Object.is(b, -0) ? 0 : b));
}
@mohamed-benoba

This comment has been minimized.

Copy link

@mohamed-benoba mohamed-benoba commented Feb 27, 2020

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

This comment has been minimized.

Copy link

@Marvelousy20 Marvelousy20 commented Feb 27, 2020

This works for me.

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

console.log(strictEquals(NaN, NaN)) ; // faslse
console.log(strictEquals(NaN, 4)) ; // false
console.log(strictEquals(3,3)) ; // true
@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented Feb 27, 2020

@Marvelousy20: Your code is wrong for the case 0, -0:

> console.log(strictEquals(0, -0), 0 === -0)
false true

But smart, that you realised that is sufficient to just check one parameter for NaN.

The second if statement can be simplified to return Object.is(a,b)

@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented Feb 27, 2020

My solution:

const isZero = n => Object.is(n, 0) || Object.is(n, -0)

const strictEquals = (a, b) => {
    if (Number.isNaN(a) || Number.isNaN(b)) return false
    if (isZero(a) && isZero(b)) return true

    return Object.is(a,b)
}

After seeing Marvelousy20's solution I realised that I could also leave out || Number.isNaN(b), but would in most cases prefer to leave it in. Without it, I think it would confuse too many people, why only one parameter is checked.

@Marvelousy20

This comment has been minimized.

Copy link

@Marvelousy20 Marvelousy20 commented Feb 27, 2020

@datenreisender Thank you for the correction.

@checkmatez

This comment has been minimized.

Copy link

@checkmatez checkmatez commented Feb 29, 2020

const strictEquals = (a,b) => {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    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)
}
@Marvelousy20

This comment has been minimized.

Copy link

@Marvelousy20 Marvelousy20 commented Feb 29, 2020

@checkmatez, Nice one, I made a small modification to your code.

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

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

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

}
console.log(strictEquals(NaN,NaN)) ; // false
console.log(strictEquals(3,3)) ;     // true
console.log(strictEquals(0,-0))      // true
@checkmatez

This comment has been minimized.

Copy link

@checkmatez checkmatez commented Feb 29, 2020

@Marvelousy20
There are bugs:

strictEquals(-0, +0) // undefined, expected: true
strictEquals(NaN, 1) // undefined, expected: false
@Marvelousy20

This comment has been minimized.

Copy link

@Marvelousy20 Marvelousy20 commented Feb 29, 2020

@checkmatez, Oh, Thank you. I didn't put an else statement. This should work just fine now:

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

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

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

    else {
        return Object.is(a,b)
    }
}
@CodetaroMiura

This comment has been minimized.

Copy link

@CodetaroMiura CodetaroMiura commented Mar 1, 2020

Here is my solution.

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

This comment has been minimized.

Copy link

@datenreisender datenreisender commented Mar 2, 2020

@CodetaroMiura This line leads to almost all falsy values being reported as equals

  if (!a && !b) return true

E.g. 0 and false appear to be equal but should not: https://jsbin.com/sareqoguju/edit?js,console

@polnikale

This comment has been minimized.

Copy link

@polnikale polnikale commented Mar 2, 2020

What about this one?

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

This comment has been minimized.

Copy link

@datenreisender datenreisender commented Mar 2, 2020

@polnikale With the line

if (Object.is(a, -b) && typeof a === typeof b) return true;

it seems to me, that you try to find a clever short solution, but with it you are really making it more cryptic and actually wrong. Just one example is, that your function returns true for 1 and -1.

@CodetaroMiura

This comment has been minimized.

Copy link

@CodetaroMiura CodetaroMiura commented Mar 2, 2020

@CodetaroMiura This line leads to almost all falsy values being reported as equals

  if (!a && !b) return true

E.g. 0 and false appear to be equal but should not: https://jsbin.com/sareqoguju/edit?js,console

Ah you're right. I will change that up, thanks.

@AymenBenAmor

This comment has been minimized.

Copy link

@AymenBenAmor AymenBenAmor commented Mar 2, 2020

This should work no ?
function strictEquals(a,b) { if (Number.isNaN(a) || Number.isNaN(b)){ return false; } return Object.is(a,b) || Object.is(a, -b) }

@Marvelousy20

This comment has been minimized.

Copy link

@Marvelousy20 Marvelousy20 commented Mar 3, 2020

@lpmtsf

This comment has been minimized.

Copy link

@lpmtsf lpmtsf commented Mar 3, 2020

@polnikale

Does not work. You use '===' and the initial rules of the challenge exclude this operator.

@calderon

This comment has been minimized.

Copy link

@calderon calderon commented Mar 4, 2020

Mine has been:

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;
  }
}
@raresportan

This comment has been minimized.

Copy link

@raresportan raresportan commented Mar 4, 2020

function strictEquals(a, b) {
   return Object.is(typeof a, typeof b) && // Same type
          !Number.isNaN(a+b) && // no NaNs
          (Object.is(a,b) || !(a+b+a)) // true (for all except NaNs or 0 & -0) or sum 0
}

/// Tests
console.log(strictEquals(NaN, NaN), NaN === NaN);
console.log(strictEquals(NaN, 4), NaN === 4);
console.log(strictEquals(0, -0), 0 === -0);
console.log(strictEquals(0, '0'), 0 === '0');
console.log(strictEquals(3,3), 3 === 3);
console.log(strictEquals('0', '-0'), '0' === '-0');
console.log(strictEquals(-0, +0), -0 === +0);
console.log(strictEquals(0, 0), 0 === 0);
console.log(strictEquals(NaN, 1), NaN === 1);
console.log(strictEquals('', 0), '' === 0);
console.log(strictEquals('', 1), '' === 1);
console.log(strictEquals('', ''), '' === '');
console.log(strictEquals(1, 1), 1 === 1);
console.log(strictEquals(false, false), false === false);
console.log(strictEquals(true, true), true === true);
console.log(strictEquals(1, -1), 1 === -1);
@quickEscape

This comment has been minimized.

Copy link

@quickEscape quickEscape commented Mar 5, 2020

function strictEquals(a, b) {
  if (typeof(a) == "number" && typeof(b) == "number") {
    return a == b;
  }
  return Object.is(a, b);
}
@NickMaslov

This comment has been minimized.

Copy link

@NickMaslov NickMaslov commented Mar 8, 2020

If we can use loose equality (==) than this simple implementation should work for all cases

function strictEquals(a, b){
  if (typeof a == 'number'&&typeof b == 'number' ) 
    return a==b

  return Object.is(a, b)
}

or even this

const strictEquals = (a, b) => typeof a === typeof b
  ? a == b
  : Object.is(a, b)
@victorfdes

This comment has been minimized.

Copy link

@victorfdes victorfdes commented Mar 10, 2020

Hello @gaearon
How about not using Object.is?

'use strict';

function strictEquals(a, b) {
  return !new Set().add(a).has(b) || new Set().add(Infinity / a).has(Infinity / b);
}

@nakhodkiin It wouldn't work as strictEquals(2, '2') would return true

@chuckrector

This comment has been minimized.

Copy link

@chuckrector chuckrector commented Mar 11, 2020

I like the solutions that draw attention to the two outliers that were mentioned in the article: NaN and -0

By those described differences, this seemed "99% correct" already:

function strictEquals(a, b) {
    return Object.is(a, b);
}

Before peeking, I stacked the outliers on top:

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

Cool exercises!

@matiangul

This comment has been minimized.

Copy link

@matiangul matiangul commented Mar 15, 2020

Here is my implementation:

function strictEquals(a, b) {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    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)
}
@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented Mar 15, 2020

@matiangul: While your solution works correctly for the cases with 0 and NaN it wrongly says other things are equal which really are not equal. Can you find these wrong positives?

@matiangul

This comment has been minimized.

Copy link

@matiangul matiangul commented Mar 15, 2020

Hah you are right @datenreisender I've oversimplified last condition.

@mohamedGamalAbuGalala

This comment has been minimized.

Copy link

@mohamedGamalAbuGalala mohamedGamalAbuGalala commented Mar 16, 2020

const strictEql =(a,b)=>{

    if(Number.isNaN(a) && Number.isNaN(b)){
        return !Object.is(a,b)
    }


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

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

   
    return Object.is(a,b)

}
@dpanov

This comment has been minimized.

Copy link

@dpanov dpanov commented Mar 18, 2020

function strictEquals(a, b) {
  // We have to be strict, after all
  if (!Object.is( typeof(a), typeof(b) )) {
    return false;
  };

  // Special case #1: NaN
  if (Number.isNaN(a)) {
    return false;
  }

  // Special case #2: 0 and -0
  if (!!Math.pow(a, b)) {
    return true;
  }

  // Fallback to Object.is for everything else
  return Object.is(a,b);
}
@eypsrcnuygr

This comment has been minimized.

Copy link

@eypsrcnuygr eypsrcnuygr commented Mar 21, 2020

And here mine;

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

@DmytroSukhariev

This comment has been minimized.

Copy link

@DmytroSukhariev DmytroSukhariev commented Mar 23, 2020

My cute code:

const { is }    = Object
const { isNaN } = Number

const isZero    = a => b => (is(a, 0) || is(b, 0))

const isNegZero = a => b => (is(a, -0) || is(b, -0))

const strictEquals = a => b => (
    (isNaN(a) && isNaN(b))
    ? false :
    (isZero(a)(b) && isNegZero(a)(b))
    ? true  :
    is(a, b)
)

My ugly tests:

const { log } = console

const toStringWithNegZero = a => ((is(a, -0)) ? '-0' : `${a}`)

const test = f => a => b => {
    const nativeResult               = (a === b)
    const fResult                    = f(a)(b)

    const inputsLabel                = `Inputs: \n    a = ${toStringWithNegZero(a)}\n    b = ${toStringWithNegZero(b)}\n`
    const fResultLabel               = `Function result: \n    ${f(a)(b)}\n`
    const nativeStrictEqualityLabel  = `Native strict equality: \n    ${a === b}\n`
    const testResultLabel = 
        (nativeResult === fResult)
        ? 'Test passed!'
        : 'Test failed!' 

    log(`===========\n${inputsLabel}${fResultLabel}${nativeStrictEqualityLabel}${testResultLabel}`)
}

const testF = test(strictEquals)

testF(NaN)(NaN)

testF(0)(-0)
testF(-0)(0)

testF(0)(0)
testF(-0)(-0)

testF(1)(1)
testF(1)(2)
testF(1)("bla bla")

And tests results:

===========
Inputs: 
    a = NaN
    b = NaN
Function result: 
    false
Native strict equality: 
    false
Test passed!
===========
Inputs: 
    a = 0
    b = -0
Function result: 
    true
Native strict equality: 
    true
Test passed!
===========
Inputs: 
    a = -0
    b = 0
Function result: 
    true
Native strict equality: 
    true
Test passed!
===========
Inputs: 
    a = 0
    b = 0
Function result: 
    true
Native strict equality: 
    true
Test passed!
===========
Inputs: 
    a = -0
    b = -0
Function result: 
    true
Native strict equality: 
    true
Test passed!
===========
Inputs: 
    a = 1
    b = 1
Function result: 
    true
Native strict equality: 
    true
Test passed!
===========
Inputs: 
    a = 1
    b = 2
Function result: 
    false
Native strict equality: 
    false
Test passed!
===========
Inputs: 
    a = 1
    b = bla bla
Function result: 
    false
Native strict equality: 
    false
Test passed!
@omeizahanif

This comment has been minimized.

Copy link

@omeizahanif omeizahanif commented Mar 25, 2020

Here's mine (I am so late to this party :D)

const strictEquals = (a, b) => {

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

  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);
}
@matt-savvy

This comment has been minimized.

Copy link

@matt-savvy matt-savvy commented Mar 26, 2020

function strictEquals(a, b) {

  // both of our special cases are numbers, so check for that
  if (Object.is(typeof a, 'number')) {
    // if a isn't a number, then BOTH can't be numbers.
    // if both aren't the same type, === will be false anyway
    // Object.is has our back here
    return Object.is(a, b);
  }

  if (Number.isNaN(a)) {
    // we only need to check one of our inputs here.
    // if one of them is NaN, it doesn't matter what the other one is,
    // ===  will always be false.
    // we don't need to check the other input because if a isn't NaN,
    // but b IS, then Object.is will output false, which is what we want.
    return false;
  }

  // if either of our inputs are -0, this will convert them to 0
  // all other number values will be left intact
  const cleanA = a + 1 - 1;
  const cleanB = b + 1 - 1;
  return Object.is(cleanA, cleanB);
}
@lzralbu

This comment has been minimized.

Copy link

@lzralbu lzralbu commented Mar 27, 2020

function strictEquals(a, b) {

  if (Object.is(a, NaN)) {
    return false;
  }
  else
  if (Object.is(a, 0) || Object.is(a, -0)) {
    return Object.is(b, 0) || Object.is(b, -0);
  }

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

This comment has been minimized.

Copy link

@blackhaj blackhaj commented Apr 1, 2020

How about this? My tests are passing but perhaps I am missing some edge cases:

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

Any feedback would be greatly appreciated. Thanks Dan for an awesome course!

@hierror

This comment has been minimized.

Copy link

@hierror hierror commented Apr 1, 2020

Hey, here goes my solution!

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

Any feedback is appreciated!

@lzralbu

This comment has been minimized.

Copy link

@lzralbu lzralbu commented Apr 1, 2020

@hierror
strictEquals(1, -1) returns true but 1 === -1 evaluates to false.

@hierror

This comment has been minimized.

Copy link

@hierror hierror commented Apr 1, 2020

@hierror
strictEquals(1, -1) returns true but 1 === -1 evaluates to false.

Thank you for testing, I've focused too much attention on the comparison between 0 and -0. I think this new solution works better.

function strictEquals(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b))
      return false
  else if (Object.is(a + b, a * 2))
      return true
  else
      return Object.is(a, b)
}
@lzralbu

This comment has been minimized.

Copy link

@lzralbu lzralbu commented Apr 1, 2020

Still wrong.

[(-0) + 0, (-0) * 2]
[ 0, -0 ]

So strictEquals(-0, 0) is false.

@lzralbu

This comment has been minimized.

Copy link

@lzralbu lzralbu commented Apr 1, 2020

How about this? My tests are passing but perhaps I am missing some edge cases:

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

Any feedback would be greatly appreciated. Thanks Dan for an awesome course!

strictEquals(NaN, NaN) is true but should be false.

@IbrahimShamma99

This comment has been minimized.

Copy link

@IbrahimShamma99 IbrahimShamma99 commented Apr 5, 2020

const strictEquals = function(a, b){
    //Case -0 === 0
    if ((Object.is(Math.sign(a),-0) && Object.is(Math.sign(b),0))|| 
    (Object.is(Math.sign(a),0) && Object.is(Math.sign(b),-0)))
    {
        return true;
    }
    //Case NaN === NaN
    if (Number.isNaN(b)&&Number.isNaN(a) )
    {
        return false;
    }
    return Object.is(a,b)
};

console.log("5===5  =>",strictEquals(5,5))  \\true
console.log("NaN===NaN  =>",strictEquals(NaN,NaN)) \\false
console.log("0===-0  =>",strictEquals(0,-0))  \\true
@tomsjansons

This comment has been minimized.

Copy link

@tomsjansons tomsjansons commented Apr 8, 2020

function strictEquals(a, b) {
  return (
    ([0, -0].includes(a) && [0, -0].includes(b)) ||
    (Object.is(a, b) && !(Number.isNaN(a) && Number.isNaN(b)))
  );
}
@akkerd

This comment has been minimized.

Copy link

@akkerd akkerd commented Apr 9, 2020

Tried a short solution. It works even for values like undefined and null too (they don't satisfy the first two if conditions):

const strictEquals = (a, b) => {
    if( Number.isNaN(a) && Number.isNaN(NaN) ){
        return false;
    }else if( !Object.is(Math.sign(a), Math.sign(b)) && Object.is(a + b, 0) ){
        return false;
    }
    return Object.is(a,b);
}
@YasirHasn9

This comment has been minimized.

Copy link

@YasirHasn9 YasirHasn9 commented Apr 21, 2020

function strictEquals(a, b) {
// check the value type of a , b
if (Object.is((typeof a) , (typeof b))) {
return Object.is(a,b)
}
return false
}

@lsfgrd

This comment has been minimized.

Copy link

@lsfgrd lsfgrd commented Apr 30, 2020

This is the solution I came up with. I don't think there's something wrong.

const 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);
}
@lazyKT

This comment has been minimized.

Copy link

@lazyKT lazyKT commented May 4, 2020

This is my solution. Please correct me if I did wrong. Thanks :D

function strictEquals (a, b) {
  if (Object.is(a, NaN) && Object.is(b, NaN))
    return false;
  else if ( Object.is(Math.abs(a), 0) && Object.is(Math.abs(b), 0))
    return true;
  return Object.is(a,b); 
}
@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented May 4, 2020

@lazyKT Trying to shortcut testing for positive and negative zero introduces an error in your solution, because Math.abs converts it's argument to a number first and there are some things that get converted to a zero. So your solution wrongly also returns true for strictEquals('0', 0). And even for strictEquals(false, null).

@lazyKT

This comment has been minimized.

Copy link

@lazyKT lazyKT commented May 4, 2020

@datenreisender Thank you so much for the review of my codes, mister. I have never consider those values when I wrote those. Now, I changed the testing for positive and negative zero. Can you please take a look?

function strictEquals(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;
  return Object.is(a, b);
}
@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented May 4, 2020

@lazyKT Yes, that new solution looks correct.

@mrspok407

This comment has been minimized.

Copy link

@mrspok407 mrspok407 commented May 4, 2020

Here's my solution and I think nobody implemented this approach before (or I missed it)

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

I'm checking whether a or b equal to 0 or -0 by adding one. In both cases the output will be 1 doesn't matter you add it to -0 or 0. In all other cases if !Object.is(a, b) is false adding 1 to both arguments will not get any influence on comparison.

@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented May 4, 2020

@mrspok407: I usually advice against trying clever solutions like the one you are doing by adding 1: For one thing they are harder to understand later, they rarely bring any advantage and often introduce subtle bugs.

Your solutions, for example, does correctly return true for 0 and -0, but it also returns true for some arguments for which it should return false. Maybe you can come up with some examples when looking at the spec on how JavaScript converts things to numbers?

@mrspok407

This comment has been minimized.

Copy link

@mrspok407 mrspok407 commented May 5, 2020

@datenreisender Thanks for the reply. I'm learning JS and programming in general just for several month now. I didn't understand what you imply me to found in the link you provided. Can you please clarify?
As for this is "clever" solution I agree with this. No reason to use it in real world over more robust and simple solutions people provided already. So, it would be no reason for me to write solution that already here.
If you can provide a scenario where my code wouldn't work as expected, please do. So me and other people in future reading this will learn.

@datenreisender

This comment has been minimized.

Copy link

@datenreisender datenreisender commented May 5, 2020

@mrspok407: In certain situations JavaScript tries to convert values so they fit better the assumed intention. Addition is such a situation, when JavaScript tries to convert the given values to strings or numbers (depending on the other argument). Because of this, you can do things like 42 + true and it is not an error (the result is 43). false and null are two things that get converted to 0 when added to number.

Because of this with your implementation strictEquals(null, 0) or even strictEquals(null, false) are true, while they should be false, just like null === 0 and null === false.

@mrspok407

This comment has been minimized.

Copy link

@mrspok407 mrspok407 commented May 5, 2020

@datenreisender Thank you! I was thinking in that way, but didn't fully get it. Now it's clear, much appreciated!

@pushkar8723

This comment has been minimized.

Copy link

@pushkar8723 pushkar8723 commented May 5, 2020

I don't think it makes a difference now but here goes my implementation 😬

function strictEquals(a, b) {
    // If either a or b is NaN, return false. Because NaN will never equal to anything. 
    if (Object.is(a, NaN) || Object.is(b, NaN)) return false;

    // If a is either of 0 or -0 *and* b too is either of 0 or -0, return true. 
    // Because I don't see sign when 0 is involved.
    if ((Object.is(a, 0) || Object.is(a, -0)) && (Object.is(b, 0) || Object.is(b, -0))) return true;

    // Speak the truth!
    return Object.is(a, b);
}
@VladislavMurashchenko

This comment has been minimized.

Copy link

@VladislavMurashchenko VladislavMurashchenko commented May 6, 2020

@lsfgrd is very similar to mine

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

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

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

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

This comment has been minimized.

Copy link

@Here21 Here21 commented May 7, 2020

Here is my answer

function strictEquals(a, b) {
    if(Number.isNaN(a) || Number.isNaN(b)) {
        return false;
    }
    // Mostly, null or undefined just equal 'Math' 0;
    // so Math method can't do this, it had to use Object.js to distinguish 0.
    if((Object.is(a, 0) || Object.is(a, -0)) && (Object.is(b, 0) || Object.is(b, -0))) {
        return true;
    }
    return Object.is(a, b)
} 
@isaac-yoon

This comment has been minimized.

Copy link

@isaac-yoon isaac-yoon commented May 9, 2020

Pretty cool!

@dboscanv

This comment has been minimized.

Copy link

@dboscanv dboscanv commented May 10, 2020

Wow πŸ˜† I'm surprised the differences between versions.

This is my func:

function strictEquals(a, b) {
	const args = Array.from(arguments);
	const isSomeValueNaN = args.some(val => Number.isNaN(val));
	const isEveryValueZero = args.every(val => Object.is(val, 0) || Object.is(val, -0));
	if (isSomeValueNaN) return false;
	if (isEveryValueZero) return true;
	return Object.is(a, b);
}
@magbello157

This comment has been minimized.

Copy link

@magbello157 magbello157 commented May 16, 2020

Here is my solution:

function strictEquals(a, b) {
  // NaN compared to NaN
  if (Object.is(a, NaN) && Object.is(b, NaN)) {
    return false;
  // 0 compared to -0
  } else if (Object.is(a, 0) && Object.is(b, -0)) {
    return true;
  // -0 compared to 0
  } else if (Object.is(a, -0) && Object.is(b, 0)) {
    return true;
  // All other comparisons return correct boolean
  } else {
    return Object.is(a, b);
  }
}
@esfxra

This comment has been minimized.

Copy link

@esfxra esfxra commented May 19, 2020

Thanks for the reference!

Seems like my implementation is similar to others and should also do the trick.

P.s. just now going through the emails.

// Cannot use === or !==
function strictEquals(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 {
    return Object.is(a, b);
  }
}
@shanshaji

This comment has been minimized.

Copy link

@shanshaji shanshaji commented May 21, 2020

`function strictEquals(a, b) { 
    let c =null;
    if(Object.is(a, -0) || Object.is(b, -0) || Object.is(a, NaN) || Object.is(b, NaN)) { 
       c = !Object.is(a,b)
     }else{
        c = Object.is(a,b)
     }
  return c;
}`

wouldn't this work?

@aquaductape

This comment has been minimized.

Copy link

@aquaductape aquaductape commented May 22, 2020

without using Object.is() isNaN() or any of the Equality operators.

// exercise if two are values are strictly equal
// without using Equality operators: ==, ===, !=, !==
// or Object.is()
const isObject = (val) => {
  if (!val) return false;
  return (typeof val).match(/object|function/);
};

const strictEquals = (a, b) => {
  // a and b are both objects
  if (isObject(a) && isObject(b)) {
    let aLength = Object.keys(a).length;
    let bLength = Object.keys(b).length;

    // amount of keys don't match
    if (aLength - bLength) {
      return false;
    }

    let isEmpty = true;
    let tempKey;
    let tempVal;

    // remove one key in a,
    // which will reflect in b
    // if it points to same object as a
    for (const key in a) {
      tempKey = key;
      tempVal = a[key];
      delete a[key];
      isEmpty = false;
      break;
    }

    // checking if a was already empty to begin with
    if (!isEmpty) {
      // check amount of keys for both again
      aLength = Object.keys(a).length;
      bLength = Object.keys(b).length;
      // if amount of keys match, they share the same object
      if (!(aLength - bLength)) {
        // restore input object, avoid side effects
        a[tempKey] = tempVal;
        return true;
      }
      // restore input object, avoid side effects
      a[tempKey] = tempVal;
      return false;
    } else {
      // it's safe to add a key since a is empty
      a.prod = true;
      if (b.prod) {
        // restore input object, avoid side effects
        delete a.prod;
        return true;
      }
      // restore input object, avoid side effects
      delete a.prod;
      return false;
    }
  }

  // if a and b are primitives or one of them are objects
  const map = {};
  map[a] = true;
  map[b] = true;
  // keys are converted to strings
  // this is problem where 0 and "0" will both result in "0"
  // storing the type as key as well is an additional measure
  map[typeof a] = true;
  map[typeof b] = true;

  // if a and b are the same, the map will only have two keys
  const result = !(Object.keys(map).length - 2);

  if (result) {
    if (map["NaN"]) return false;
  }

  return result;
};

/***** Tests  ****/

const objA = { docker: "πŸ‹" };
const objB = { docker: "πŸ‹" };
const objC = { key: "🐠", docker: "πŸ‹" };
const objD = {};
const arrA = ["🌊", "πŸ‘‹"];
const arrB = ["🌊", "πŸ‘‹"];
const arrC = ["🌊", "πŸ‘‹", "wut"];
const arrD = [];
const funcA = () => {
  return 42;
};
const funcB = () => {
  return 42;
};

console.log(NaN === NaN, strictEquals(NaN, NaN));
console.log(NaN === 4, strictEquals(NaN, 4));
console.log(0 === -0, strictEquals(0, -0));
console.log(0 === "0", strictEquals(0, "0"));
console.log(3 === 3, strictEquals(3, 3));
console.log("0" === "-0", strictEquals("0", "-0"));
console.log(-0 === +0, strictEquals(-0, +0));
console.log(0 === 0, strictEquals(0, 0));
console.log("" === 0, strictEquals("", 0));
console.log("" === 1, strictEquals("", 1));
console.log("" === "", strictEquals("", ""));
console.log(1 === 1, strictEquals(1, 1));
console.log(1 === -1, strictEquals(1, -1));
console.log(undefined === null, strictEquals(undefined, null));
console.log(null === null, strictEquals(null, null));
console.log(Infinity === Infinity, strictEquals(Infinity, Infinity));
console.log(Infinity === -Infinity, strictEquals(Infinity, -Infinity));
console.log("hi" === "hi", strictEquals("hi", "hi"));
console.log("hi" === "bye", strictEquals("hi", "bye"));
console.log(true === true, strictEquals(true, true));
console.log(true === false, strictEquals(true, false));
console.log(false === false, strictEquals(false, false));
console.log(funcA === funcA, strictEquals(funcA, funcA));
console.log(funcA === funcB, strictEquals(funcA, funcB));
console.log(objA === objA, strictEquals(objA, objA));
console.log(objA === objB, strictEquals(objA, objB));
console.log(objA === objC, strictEquals(objA, objC));
console.log(objD === objD, strictEquals(objD, objD));
console.log({} === {}, strictEquals({}, {}));
console.log(arrA === arrA, strictEquals(arrA, arrA));
console.log(arrA === arrB, strictEquals(arrA, arrB));
console.log(arrA === arrC, strictEquals(arrA, arrC));
console.log(arrD === arrD, strictEquals(arrD, arrD));
console.log([] === [], strictEquals([], []));
console.log({} === [], strictEquals({}, []));
@shivamsinghchahar

This comment has been minimized.

Copy link

@shivamsinghchahar shivamsinghchahar commented May 22, 2020

Here's my solution

Not very fancy though

const strictEquals = (a, b) => {
  return a == b && typeof a == typeof b
}
@aquaductape

This comment has been minimized.

Copy link

@aquaductape aquaductape commented May 22, 2020

@chaharshivam
i like it πŸ‘
You can make it even more compact

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

This comment has been minimized.

Copy link

@shivamsinghchahar shivamsinghchahar commented May 22, 2020

@chaharshivam
i like it
You can make it even more compact

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

Thanks a lot!

@Mert1980

This comment has been minimized.

Copy link

@Mert1980 Mert1980 commented May 23, 2020

Here is my solution!

function strictEquals(a, b) {
  if (Number.isNaN(a) && Number.isNaN(b)) return !Object.is (a, b)
  if ((a == -0 && b == 0) || (a == 0 && b == -0)) return !Object.is (a, b)
  return Object.is (a, b)
  }
@maksymilian-majer

This comment has been minimized.

Copy link

@maksymilian-majer maksymilian-majer commented May 23, 2020

function strictEquals(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    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);
}

function assert(outcome, desc) {
  console.log(`${desc}: ${outcome ? "true" : "false"}`);
}

assert(strictEquals('a', 'b'), '"a" === "b"');
assert(strictEquals(-0, 0), '-0 === 0');
assert(strictEquals(0, -0), '0 === -0');
assert(strictEquals(NaN, NaN), 'NaN === NaN');
assert(strictEquals(undefined, undefined), 'undefined === undefined');
assert(strictEquals(null, null), 'null === null');
assert(strictEquals('a', 'a'), '"a" === "a"');
assert(strictEquals(1, 5), '1 === 5');
assert(strictEquals(2, 2), '2 === 2');

@gthrm

This comment has been minimized.

Copy link

@gthrm gthrm commented May 24, 2020

I think, it works

function strictEquals(a, b) {
    if (Number.isNaN(a) && Number.isNaN(b)) {
        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);
}
@quirogamauricio

This comment has been minimized.

Copy link

@quirogamauricio quirogamauricio commented May 24, 2020

I think, it works

function strictEquals(a, b) {
    if (Number.isNaN(a) && Number.isNaN(b)) {
        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);
}

I don't think so:
strictEquals(0, 1) // true

@quirogamauricio

This comment has been minimized.

Copy link

@quirogamauricio quirogamauricio commented May 24, 2020

My solution:

function strictEquals(a, b) {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    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);
}
@krylenger

This comment has been minimized.

Copy link

@krylenger krylenger commented May 29, 2020

Here is my solution:

const strictEquals = (a, b) => {
    if (Object.is(a, NaN) && Object.is(b, NaN)) {
        return false;
    } else if (Object.is(a, b)) {
        return true;
    } else if ((Object.is(a, 0) && Object.is(b, -0)) || 
                (Object.is(a, -0) && Object.is(b, 0))) {
        return true;
    } else {
        return false;
    }
}
@krylenger

This comment has been minimized.

Copy link

@krylenger krylenger commented May 29, 2020

Here's my solution

Not very fancy though

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

we are not allowed to use loose comparison '==' in this exercise.

@kuzzzzz

This comment has been minimized.

Copy link

@kuzzzzz kuzzzzz commented May 29, 2020

yeah i go

@mellamopepino

This comment has been minimized.

Copy link

@mellamopepino mellamopepino commented May 30, 2020

Complete implementation, including handling of undefined:

// implement a === b without using ===
function strictEquals(a, b) {
	// handle NaN
	if (![a, b].includes(undefined) && isNaN(a) && isNaN(b)) {
		return false;
	}
	// handle -0
	if ([0, -0].includes(a) && [0, -0].includes(b)) {
		return true;
	}
	
	 return Object.is(a, b);
}

This fails with strings, because isNaN("somestring") results in true. :/

@mellamopepino

This comment has been minimized.

Copy link

@mellamopepino mellamopepino commented May 30, 2020

I think the easiest and readable way is to check exceptions and then just return the result of Object.is. I believe this works:

const 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);
}
@csalmeida

This comment has been minimized.

Copy link

@csalmeida csalmeida commented May 31, 2020

I've done it like this, hopefully it's fine! So interesting to see many different ways of solving the same problem.

function strictEquals(a,b) {
   if (Number.isNaN(a) && Number.isNaN(b)) {
      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)
}

strictEquals(2,5) // false
strictEquals(2,2) // true

strictEquals(null, null) // true
strictEquals(undefined, undefined) // true

strictEquals({},{}) // false
strictEquals([],[]) // false
strictEquals(function () {}, function () {}) // false

strictEquals(0,-0) // true
strictEquals(-0,0) // true

strictEquals("","") // true
strictEquals("","a") // false

strictEquals(NaN,NaN) // false
@yokodev

This comment has been minimized.

Copy link

@yokodev yokodev commented Jun 12, 2020

I stole the tests from @csalmeida :p
Here I'm only checking for the specific exercise and omitting safe checking .i.e nulls. etc.

function strictEquals(a,b){
  //special case #1
 	if(Number.isNaN(a) && Number.isNaN(b)){
    return false
  }
  //special case#2
  if(Object.is(a,-0) && Object.is(b,0)){
    return true
  }
  //special case #2
 if(Object.is(a,0) && Object.is(b,-0)){
    return true
  }
  return Object.is(a,b)
}
strictEquals(2,5) // false
strictEquals(2,2) // true

strictEquals(null, null) // true
strictEquals(undefined, undefined) // true

strictEquals({},{}) // false
strictEquals([],[]) // false
strictEquals(function () {}, function () {}) // false

strictEquals(0,-0) // true
strictEquals(-0,0) // true

strictEquals("","") // true
strictEquals("","a") // false

strictEquals(NaN,NaN) // false
@jwohllk

This comment has been minimized.

Copy link

@jwohllk jwohllk commented Jun 15, 2020

Here is my solution

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)
}
@curiouskaran

This comment has been minimized.

Copy link

@curiouskaran curiouskaran commented Jun 24, 2020

How is my solution. can we use == as you mentioned === , !== not allowed.

const strictEquals = (a,b) => {
    if((typeof a == typeof b) && (a == b)) return true;
    return false;
}
@shikelong

This comment has been minimized.

Copy link

@shikelong shikelong commented Jun 29, 2020

//Write a function called strictEquals(a, b) that returns the same value as a === b. Your implementation must not use the === or !== operators.
function strictEquals(a, b){
  if (Number.isNaN(a) || Number.isNaN(b)){
    return false; 
  }
  //+0/-0
  if (isEqual(a, -0) && isEqual(b, +0) || isEqual(a, +0) && isEqual(b, -0)){
    return true;
  }
  return Object.is(a, b);
};

function isEqual(x, y) {
    var obj = {};
    Object.defineProperty(obj, 'z', { value: x, configurable: false });
    try {
        Object.defineProperty(obj, 'z', { value: y });
    } catch (e) {
        return false
    };
    return true;
}
@aNyMoRe0505

This comment has been minimized.

Copy link

@aNyMoRe0505 aNyMoRe0505 commented Jul 2, 2020

my version

function strictEquals(a, b) {
  if (Object.is(typeof a, 'number') && Object.is(typeof b, 'number')) {
      if (Number.isNaN(a) && Number.isNaN(b)) return false;
    
      if (!a && !b) return true;
  }
  
  return Object.is(a, b);
}
@glecetre

This comment has been minimized.

Copy link

@glecetre glecetre commented Jul 18, 2020

Here's what I came up with:

function strictEquals(a, b) {
  if (Number.isNaN(a) || Number.isNaN(b)) {
    return false
  }
  
  return Object.is(a, b) || Object.is(a, a+b)
}
@jinglf000

This comment has been minimized.

Copy link

@jinglf000 jinglf000 commented Jul 18, 2020

my code

const strictEqual = (a, b) => {
  if (Math.isNaN(a) || Math.isNaN(b)) return false;
  if (Math.abs(a) === 0 &&   Math.abs(b) === 0)return true;
  return Object.is(a,b);
}
@kojoru

This comment has been minimized.

Copy link

@kojoru kojoru commented Jul 18, 2020

@glecetre strictEquals(1,0) returns true in your case.

@rawatmanoj

This comment has been minimized.

Copy link

@rawatmanoj rawatmanoj commented Jul 22, 2020

Doing any math operation on NaN will give output NaN only. I used it for my answer.

function strictEquals(a, b) {
  if (Object.is(typeof a, 'number') && Object.is(typeof b, 'number')) {
    if (Object.is(Math.abs(a), 0) && Object.is(Math.abs(b), 0)) {
      return true;
    }

    if (Object.is(0 * a, 0) && Object.is(0 * b, 0)) {
      return Object.is(a, b);
    } else {
      return false;
    }
  }

  return Object.is(a, b);
}

A shorter solution:

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

  return Object.is(a, b);
}

@rawatmanoj

This comment has been minimized.

Copy link

@rawatmanoj rawatmanoj commented Jul 22, 2020

Here's what I came up with:

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

@glecetre strictEquals(-1,0) gives true in your case

@ryanwabraham

This comment has been minimized.

Copy link

@ryanwabraham ryanwabraham commented Jul 23, 2020

I think this should do it. Fun little exercise!

function strictEquals(a, b) {
  if (Object.is(a, b)) {
    // NaN !== NaN
    if (Object.is(a, NaN)) return false;
    return true;
  } else {
    // 0 === -0
    // -0 === 0
    if (Object.is(a, 0) && Object.is(b, -0)) return true;
    if (Object.is(a, -0) && Object.is(b, 0)) return true;
    return false;
  }
}
@hanielbaez

This comment has been minimized.

Copy link

@hanielbaez hanielbaez commented Jul 31, 2020

Write a function called strictEquals(a, b) that returns the same value as a === b. Your implementation must not use the === or !== operators

const strictEquals = (a, b) => {
    //Are they NaN?
    if (Object.is(a, NaN) || Object.is(b, NaN)) {
        return false
    }
    //Are a and b numbers
    if (Object.is(typeof (a), 'number') && Object.is(typeof (b), 'number')) {
        const aString = a.toString()
        const bString = b.toString()

        return Object.is(aString, bString)
    }
    return Object.is(a, b)
}


const testEqual = (a, b) => {
    console.log(`${((a === b) === strictEquals(a, b)) ? 'PASS' : 'FAIL'}`)
}

//some test
runTest(-0, -0)
runTest(-0, 0)
runTest(-0, -00)
runTest(-0, '-0')
runTest(-0, null)
runTest(-0, false)

runTest(NaN, NaN)
runTest(NaN, 'NaN')
runTest(NaN, 0)
runTest(NaN, false)
runTest(NaN, null)
runTest(NaN, -0)

runTest(1, 1)
runTest(1, -0)
runTest(1, '1')
runTest(1, null)
runTest(1, true)
runTest(1, false)

runTest('hola', 'hola')
runTest('hola', -0)
runTest('hola', '1')
runTest('hola', null)
runTest('hola', true)
runTest('hola', false)

@mhm13dev

This comment has been minimized.

Copy link

@mhm13dev mhm13dev commented Aug 3, 2020

function strictEquals(a, b) {
  if (Number.isNaN(a) && Number.isNaN(b)) {
    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);
}

const runTest = (a, b) => {
    console.log(`${((a === b) === strictEquals(a, b)) ? 'PASS' : 'FAIL'}`)
}

runTest(-0, -0)
runTest(-0, 0)
runTest(-0, -00)
runTest(-0, '-0')
runTest(-0, null)
runTest(-0, false)

runTest(NaN, NaN)
runTest(NaN, 'NaN')
runTest(NaN, 0)
runTest(NaN, false)
runTest(NaN, null)
runTest(NaN, -0)

runTest(1, 1)
runTest(1, -0)
runTest(1, '1')
runTest(1, null)
runTest(1, true)
runTest(1, false)

runTest('hola', 'hola')
runTest('hola', -0)
runTest('hola', '1')
runTest('hola', null)
runTest('hola', true)
runTest('hola', false)

I have ran all the possible tests mentioned by @NoobBaez in his comment. All tests are passed!
https://gist.github.com/gaearon/08a85a33e3d08f3f2ca25fb17bd9d638?ck_subscriber_id=932289303#gistcomment-3399619

@kkxley

This comment has been minimized.