4

So in JavaScript we have three equality comparison operators. I've been reading the ECMAScript specification and looking at how they work. Something struck me. The Object.is() built in function has less steps to it's comparison and it has a greater chance of terminating early than the other operators. So does this make Object.is() function faster than the other operators?

Here are the specification snippets:

Object.is()

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then

    a. If x is NaN and y is NaN, return true.

    b. If x is +0 and y is -0, return false.

    c. If x is -0 and y is +0, return false.

    d. If x is the same Number value as y, return true.

    e. Return false.

  3. Return SameValueNonNumber(x, y).

Loose equals ==

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is the same as Type(y), then

    a. Return the result of performing Strict Equality Comparison x === y.

  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ! ToNumber(y).
  5. If Type(x) is String and Type(y) is Number, return the result of the comparison ! ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ! ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ! ToNumber(y).
  8. If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

Strict equals ===

The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is different from Type(y), return false.

  2. If Type(x) is Number, then

    a. If x is NaN, return false.

    b. If y is NaN, return false.

    c. If x is the same Number value as y, return true.

    d. If x is +0 and y is -0, return true.

    e. If x is -0 and y is +0, return true.

    f. Return false.

  3. Return SameValueNonNumber(x, y).

If someone who works on JavaScript compilers could answer that question, that would be great!

bezbos.
  • 1,551
  • 2
  • 18
  • 33
  • 2
    The best way to check is through test. See [this](https://jsperf.com/object-is-vs-pure-javascript-check) from jsPerf. According to these tests, `Object.is` is indeed faster in all cases. – yqlim Jul 11 '19 at 06:28
  • 1
    @YongQuan That doesn't compare `Object.is` to `===`. It compares `Object.is` to a function call with a condition in it and potentially several equality checks and a couple divisions – Paul Jul 11 '19 at 06:52
  • @Paulpro just find another jsPerf test on the web. There are plenty when I last searched. You can write your own test even. – yqlim Jul 11 '19 at 06:54
  • All performance questions that actually matter significantly to your implementation should be resolved with actual testing. Define some test cases that are relevant to your particular code and design a jsperf that compares them. See which way is faster. Try several JS engines as performance can vary. Chances are the difference is meaningless in real code most of the time, but if you are really curious, then design a test that represents test cases that you would actually care about and measure. Conjecture === guess. Measurement === fact. – jfriend00 Jul 11 '19 at 07:41
  • Most notably, [`Object.is` is a **different** equality than other operators](https://stackoverflow.com/q/30543190/1048572) - so use the one that you need! – Bergi Jul 11 '19 at 08:20
  • 1
    Note that step 2 of `===` is a standard IEEE comparison, so there is probably a single-instruction version of it. On the other hand, step 2a of `Object.is` is a comparison of two sets (since `NaN` has multiple representations but they all are treated as equivalent), so a straight bitwise comparison may not be sufficient. – Raymond Chen Jul 11 '19 at 14:00
  • Hell yes! The legend @RaymondChen has answered my question! It's an honor! – bezbos. Jul 11 '19 at 16:55
  • @RaymondChen I wouldn't mind selecting your answer as the solution because it does make sense that if step 2 of `===` has a single instruction version of it that it would be the fastest comparison. – bezbos. Jul 11 '19 at 17:05

1 Answers1

2

Less steps in the spec do not necessarily mean less steps in the implementation. All kinds of optimizations apply here. So in the end, all we can do is to actually race the horses! (in your real world usecase, some synthetic while(true) Object.is(1, 1); won't generate any useful results). If it is really (notably) faster, does it make your code better, e.g. is

      Object.is(user.age, 3)

clearer than

      user.age === 3

?

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • In this case I'm pretty sure it's less steps in the implementation. There is no coercion with the `===` and `Object.is()`. I am aware that `===` is cleaner, but that wasn't the point of the question :/ Tbh `===` is a clear winner here, because the only differences between it and `Object.is()` are: it doesn't check for signed zeroes and it's not a function call. So `===` is cleaner and might even be faster! But I want someone to give me certain answer. – bezbos. Jul 11 '19 at 08:27
  • @BoškoBezik If you are not comparing values of different types, then in performance-sensitive code all major engines do optimise out the type check, and the coercion, anyway. That's why `==` is usually just as fast as `===` (in good code that doesn't make use of the coercion). – Bergi Jul 11 '19 at 10:43
  • @JonasWilms If you want to look at implemented code, be my guest. I'm not going trough that trouble just to see which comparison is faster. So I'll "guess" that `Object.is()` the fastest. @Bergi I'm aware that the modern compilers are phenomenal at optimizing code. It's very likely it does get optimized away since engines such as Google's V8 do have multiple passes for optimization in many cases. But despite this I wouldn't rely on every little thing being optimized away. – bezbos. Jul 11 '19 at 12:03