11

JavaScript's quirky weakly-typed == operator can easily be shown to be non-transitive as follows:

var a = "16";
var b = 16;
var c = "0x10";
alert(a == b && b == c && a != c); // alerts true

I wonder if there are any similar tricks one can play with roundoff error, Infinity, or NaN that could should show === to be non-transitive, or if it can be proved to indeed be transitive.

Ray Toal
  • 86,166
  • 18
  • 182
  • 232

3 Answers3

3

The === operator in Javascript seems to be as transitive as it can get.

NaN is reliably different from NaN:

>>> 0/0 === 0/0
false
>>> 0/0 !== 0/0
true

Infinity is reliably equal to Infinity:

>>> 1/0 === 1/0
true
>>> 1/0 !== 1/0
false

Objects (hashes) are always different:

>>> var a = {}, b = {};
>>> a === b
false
>>> a !== b
true

And since the === operator does not perform any type coercion, no value conversion can occur, so the equality / inequality semantics of primitive types will remain consistent (i.e. won't contradict one another), interpreter bugs notwithstanding.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • +1 Ah, okay, this can be extended to a more formal full proof by cases on the 6 types of JavaScript: undefined, null, number, boolean, string, and object. Every value of every type is `===` ONLY to itself (with the exception of NaN which does not "hurt") with no overlaps even with object. – Ray Toal Oct 01 '11 at 20:41
  • @Ray, to be fair, the `null` type is still [a work in progress](http://wiki.ecmascript.org/doku.php?id=harmony:typeof_null) to this day (e.g. `typeof null` returns `object` in my Firefox 6). The sixth type is actually `function`, which is distinct from `object` because it has to implement `call()`. – Frédéric Hamidi Oct 01 '11 at 20:57
  • @RayToal Check this [answer](http://stackoverflow.com/questions/7622671/is-the-javascript-operator-provably-transitive/7622921#7622921) – Lime Oct 01 '11 at 20:57
  • @FrédéricHamidi Thanks. I am aware of the workings of `typeof` and the fact that `typeof null` is `"object"` and that the operator returns `"function"` but the workings of this operator is orthogonal to the fact that ECMAScript 5 has six types, regardless of what this operator says. See Chapter 8 of the [ECMAScript 5 Spec](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf); it is perfectly clear about the six ECMAScript language types. – Ray Toal Oct 02 '11 at 07:55
2

If you look at the spec (http://bclary.com/2004/11/07/#a-11.9.6) you will see that no type coercion is being made. Also, everything else is pretty straightforward, so maybe only implementation bugs will make it non-transitive.

deviousdodo
  • 9,177
  • 2
  • 29
  • 34
  • Thanks for the link to the spec. A positive proof will have to be made by cases on this definition. I'll try working it out over the next day or so and will accept if it pans out. – Ray Toal Oct 01 '11 at 20:28
1

Assuming you have variable a,b, and c you can't be 100% certain as shown here. If someone is doing something as hackish as above in production, well then you probably have bigger problems ;)

var a = 1;
var b = 1;
Object.defineProperty(window,"c",{get:function(){return b++;}});

alert(a === b && b === c && a !== c); // alerts true
Lime
  • 13,400
  • 11
  • 56
  • 88
  • 1
    Nice one, found that as well but it's rather cheating :) After all, it's not the `===` that's failing, but rather the fact that the variables are changing. I guess it's implied that `a`, `b` and `c` stay to the same value in the definition of transitivity. – pimvdb Oct 01 '11 at 20:58
  • 1
    @pimvdb In the context of what the coder sees `a`,`b`, and `c` are not changing, and therefore it is not transitive `a === b && b === c && a !== c` but hey I guess that is stretching it :D – Lime Oct 01 '11 at 21:02
  • @Lime yes very clever, but I would say yes it's a stretch. I was asking about transitivity in terms of _values_, not _variables_. The difference matters, but it's a very cool illustration nevertheless! – Ray Toal Oct 02 '11 at 07:47