What is JavaScript's behavior when paring objects with integers? For example:
var result = { test: 'blah' };
if (result < 0) {
// when is this portion processed?
}
I am currently working with a result
variable that could be either an integer (error code) or an object holding further details.
I guess I could use parseInt()
or parseFloat()
but I'm quite interested in knowing the shortest possible way to handle these situations...
What is JavaScript's behavior when paring objects with integers? For example:
var result = { test: 'blah' };
if (result < 0) {
// when is this portion processed?
}
I am currently working with a result
variable that could be either an integer (error code) or an object holding further details.
I guess I could use parseInt()
or parseFloat()
but I'm quite interested in knowing the shortest possible way to handle these situations...
- 4 Did you try it? – JJJ Commented Dec 17, 2017 at 9:24
- 1 Hello Josan. Yes, but I'm wondering in there are any differences between JS engines and if a general rule has been defined... – user9109298 Commented Dec 17, 2017 at 9:26
-
An alternative strategy is to have
result
always be an object with an error code (that is eg. 0 when no error has occurred) and a value. This way you don't give the value ofresult
itself two responsibilities. – Grav Commented Dec 17, 2017 at 14:40 -
1
@groslouis Looking at the ECMAScript 2015 specification (specifically sections 12.9,3, 7.2.11, 7.1.1, 19.1.3.6, and 7.1.3.1), it would appear that the correct result of
{ 'test': 'blah' } < 0
should always befalse
in conforming implementations. The same should apply for any object with the standardtoString
andvalueOf
functions in the Object prototype. – LegionMammal978 Commented Dec 17, 2017 at 15:09
6 Answers
Reset to default 6var result = {test: 'blah'};
if(result) {
if (typeof result === 'object') {
// do something
} else if (typeof result === 'number') {
// do something
}
}
I'm wondering [...] if a general rule has been defined
Yes. The rules are described in JavaScript specification. For your example:
{ test: "blah" } < 0
I have highlighted the sections and rules involved:
11.8.5 The Abstract Relational Comparison Algorithm
[...]
1.a Let px be the result of calling ToPrimitive(x, hint Number).
The expression { test: "blah" }
ends up as "[object Object]"
3.a Let nx be the result of calling ToNumber(px).
The expression "[object Object]"
ends up as NaN
3.c If nx is NaN, return undefined.
The result of algorithm is undefined
.
11.8.1 The Less-than Operator ( < )
[...]
6. If r is undefined, return false. Otherwise, return r.
The end result is false
.
Javascript will call the valueOf() method on the object automatically if you are paring it to an integer. Similarly, when paring to a string, the toString() method is used.
If you are not the creator of the object, there may or may not be a valueOf function, so the behavior of using a parison operator can be unexpected if you haven't created the objects or done some additional testing logic and are just paring objects and integers.
https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators
The following snippet shows some parisons in action.
var five = {
value: 5,
valueOf: function() {
return this.value
}
};
var billion = {
value: 1000000000
};
console.log ( five.valueOf() );
console.log ( billion.valueOf() );
console.log ( billion > five );
console.log ( NaN > five );
console.log ( 6 > five );
console.log ( 4 > five );
Document on developer.mozilla says that JS parison logic when operand A is an Object and operand B is a Number, is defined this way:
ToPrimitive(A) == B
where
ToPrimitive(A) attempts to convert its object argument to a primitive value, by attempting to invoke varying sequences of A.toString and A.valueOf methods on A.
Additionally, Mozilla JavaScript Reference states :
If the method is not overridden in a custom object, toString() returns "[object type]".
and
Starting in JavaScript 1.8.5 toString() called on null returns [object Null], and undefined returns [object Undefined], as defined in the 5th Edition of ECMAScript and a subsequent Errata.
So it is reasonable to say that in case of parison with a Number, an Object will always be converted to a String.
Which is then handled this way:
ToNumber(A) === B
ToNumber(A) attempts to convert its argument to a number before parison. Its behavior is equivalent to +A (the unary + operator).
Finally, Unary Plus doc states that:
If it cannot parse a particular value, it will evaluate to NaN.
Same doc on developer.mozilla present a summary table showing that paring a Number with NaN does always return false.
So, unless in scenarios raised by @JasonB, the given code should work.
However, to avoid any error due to data-structure, the answer given by @ John Kennedy is to be preferred.
You can check if result is an integer with result.isInteger()
first and then perform whatever is needed if it is or treat it as an object otherwise.
I suggest that you test the type of the result
variable to determine if its a number or an object.
Test for an Object:
typeof result === 'object'
Test for a Number:
Number.isInteger(result)