22

So in most cases I've been able to use something similar to these lines, but Javascript has given me this weird result.

If I take some value and it turns out to be undefined, when compared to an integer, it does not appear to be less than or greater than any number. Why is this?

if(undefined < 1 || undefined >= 1)
    alert("yes");
else
    alert("no");

//this always alerts no

JSFiddle

bjb568
  • 11,089
  • 11
  • 50
  • 71
Liftoff
  • 24,717
  • 13
  • 66
  • 119

3 Answers3

20

There is no operator '<' can not be applied to type 'undefined' error in JavaScript as you would find in other typed languages. As such, JavaScript evaluates incompatible types with an operator to false.

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • Oh okay that makes sense. So is undefined it's own type? Can an alternative would be to just use `!== undefined`? – Liftoff Mar 02 '14 at 22:33
  • `undefined` is actually a *read-only* reference to a global object that contains a primitive value of `undefined`. Since `!==` compares if two objects are the same, then `1 !== undefined` would be true because they are not the same object. – Reactgular Mar 02 '14 at 22:35
  • @cgTag, Where's the source? – Pacerier Sep 28 '17 at 20:13
  • @Parcerier The spec defines how the relational operators should behave including when `undefined` is one of the operands: http://www.ecma-international.org/ecma-262/5.1/#sec-11.8. In particular, it mentions that "ToNumber" is called on the operand which converts `undefined` to `NaN`, and then explains that if `NaN` is the operand, the comparison returns false. – rmacklin Oct 11 '17 at 19:30
  • 1
    Here is the [current specification](//tc39.es/ecma262/#sec-relational-operators-runtime-semantics-evaluation). Relational expressions use the abstract operation IsLessThan, which, after handling string comparison, coerces both operands to numeric types using the abstract operation ToNumeric. `1` stays `1`, `undefined` gets coerced to `NaN`. IsLessThan returns `undefined` if one of the coerced operands is `NaN`, therefore the relational expression evaluates as `false`. This answer is misleading, incomplete, outdated. What are “incompatible types”? `123n < "124"` does not result in `false`. – Sebastian Simon Dec 20 '21 at 13:09
4

That's just how javascript works. If either side can't be converted to a number (strings can, by code point comparison: '2' < '3' && '186' < '4'), than number comparisons will return false (works with >, <, <=, >=).

bjb568
  • 11,089
  • 11
  • 50
  • 71
  • 1
    Not exactly true; I believe strings compare `<`/`>` with code points, not converting them to numbers; for example: `'12' < '2'` – Turner Hayes Jul 22 '16 at 18:06
  • @TurnerHayes I guess code points *are* numbers, just not the same as what you'd get with parseFloat. – bjb568 Jul 23 '16 at 03:59
  • 2
    Right, but my point was just that the example was misleading; `'2' < '3'` is true, but not because it coerces the two sides to numbers (i.e. `Number('2') < Number('3')`), but because it compares each string codepoint-by-codepoint, and the codepoint for '2' is less than the codepoint for '3'. In particular this gives the result above, which it would not give if it coerced them to numbers. – Turner Hayes Jul 23 '16 at 22:25
1

Might be a little tangential, but I'd like to introduce null into this topic to demonstrate an elusive pitfall.
When using <, <=, >, >= with null or undefined, the result is generally considered to always be false. However, there's one exception: Infinity

console.log(undefined < Infinity); // false, as expected
console.log(null < Infinity); // true, surprise!

Also notably, this also applied to the string "Infinity"

console.log(undefined < "Infinity"); // false
console.log(null < "Infinity"); // true, surprise again!
console.log(null < "infinity"); // false, it's case-sensitive

I discovered this weird behavior accidentally, and have no idea why the hell JavaScript behaves this way. But anyway, like it or not, this is JavaScript.
Hopefully, this may help someone one day.

0x269
  • 688
  • 8
  • 20