1

At some point of my code I need to know that value is changed or not.

Something like this:

let a = {x:func1()};
let old_x = a.x;
func2(a);

if(x === old_x)
    console.log(`x wasn't changed`);
else
    console.log(`x is changed`);

And this code worked for some time but I encountered 'NaN' And for NaN specs says NaN !== NaN will give 'true'... well this was quite a surprise to me, and now I wonder:

  • Is there a uniform way in JavaScript to compare two values are the same?
  • Is 'NaN' the only one special case in JavaScript and the following condition is a safe way to compare two values for equality?

    x === old_x || isNaN(old_x) && isNaN(x)
    

Notice: For my case 'same' means

1 === 1 => true
null === null => true
undefined === null => false
undefined === undefined => true
NaN === NaN => true
'0' === 0 => false
Infinity === Infinity => true
...etc

Objects, arrays, functions and other 'reference types' are compared by reference: i.e

let a = b = {}
a === b => true
but
a === {} => false
Yuri Yaryshev
  • 991
  • 6
  • 24

2 Answers2

2

Is 'NaN' the only one special case in Javascript and the following condition is a safe to compare two values for equallity?

Yes, exactly. For comparing the values NaN is the only exception, for comparing two variables / properties, such as:

 a === a

it can be fun

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • the linked answer is related to something like `a == 1 && a == 2` and is specifically talking about the double equals (which can trigger potential coercion method executions and thus side effects). It doesn't show that `a === a` can cause any issue in this case. – Pac0 Oct 05 '18 at 08:12
  • @pac0 `with({ get a() { return ~~(Math.random() * 100); } }) { console.log(a === a); }` – Jonas Wilms Oct 05 '18 at 09:55
1

NaN is indeed a special case. It's a special 'unique value' on that respect.


EDIT : I removed the part about objects, since you are aware of object reference comparisons.


The following condition is a safe way to compare two values for equality :

old_x === x || isNaN(old_X) && isNaN(x)

Not at all !

This can return true for instance if old_x and x are different strings not comparable to numbers.

Example, isNaN("a") and isNaN("b") will both return true!

You can use something similar, but you will have to test for the type of old_x and x to be "number" as well :

`old_x === x || typeof(old_x) === 'number' && typeof(x) === 'number' && isNaN(old_x) && isNaN(x)`

is ok for values.

Community
  • 1
  • 1
Pac0
  • 21,465
  • 8
  • 65
  • 74