-
-
Save gaearon/08a85a33e3d08f3f2ca25fb17bd9d638 to your computer and use it in GitHub Desktop.
// 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; | |
} | |
} | |
} |
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);
};
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
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.
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)
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);
}
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
}
}
}
My solution is
function strictEqual(a: unknown, b: unknown) {
if (Object.is(a, NaN)) return false
return new Set([a]).has(b)
}
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);
}
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;
}
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
}
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]);
}
}
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);
}
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)
}
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);
}
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);
};
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
}
}
}
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);
}
}
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);
}
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)
}
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)
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);
}
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)
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);
}
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
}
}
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);
}
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);
}
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=.
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));
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)
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);
}
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);
}
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
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 :-)
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);
}
//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;
}
}
}`
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");
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)
}
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);
}
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.
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);
}
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))
);
};
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)
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);
};
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)
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
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);
}
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)
}
}
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;
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));
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.
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);
}
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)
}
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.
function strictEquals(a,b){
if(typeof a === 'number' && typeof b === 'number'){
return a == b
}
return Object.is(a,b)
}
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)))
}
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);
}
Any inputs on what I'm missing would be appreciated