-
-
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; | |
} | |
} | |
} |
ooade
commented
Jan 26, 2022
My answer 🐥
function strictEquals(a, b) {
if (Object.is(a, b)) {
if (Object.is(a, NaN) || Object.is(b, NaN)) {
return false
} else {
return true
}
} else {
if ((Object.is(a, -0) && Object.is(b, 0)) ||
Object.is(b, -0) && Object.is(a, 0)) {
return true
} else {
return false
}
}
}
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)