This is the second part of a series “All about types” in Javascript.
- The basics – types and general rules of conversion
- Automatic type conversion
- Explicit type conversion
- Type detection
Automatic type conversion
You have seen it before:
var element = document.getElementById("someId"); if (element) { // do something }
That’s an automatic type conversion. The if-statement expects a boolean value, and if the given expression does not return one, the result is converted. document.getElementById either returns an object or null. Null is converted to false, any object to true. That’s why constructions as the above work.
In general, every time an operator or a statement expects a value of a certain type but a different type is given, automatic type conversion occurs.
There are several statements that require some special type and do type conversion when neccessary. That’s the if-statement, while and do-while and the for-statement. They all require booleans, so other types are converted to boolean.
The most common operators are the mathematical operators, such as + and -, and the comparison operator == (and their comrades +=, -= etc. and !=). I will cover the uglier operators first.
Automatic type conversion when dealing with the + operator
The + operator is an ugly element of Javascript. While it’s also overloaded in other languages, it’s also clear (and intuitive) what happens there. That’s different from Javascript. What’s the intuitive way to add a boolean to an object? Is there any way to define some semantics for adding a boolean to an object? I can’t think of one. Yet it can be done in Javascript.
When dealing with two numbers, the + operator adds these. When dealing with two strings, it concatenates.
3 + 5; // 8 "hello " + "world"; // "hello world" "3" + "5"; // "35"
When one operand is a string and the other is not, the other is converted to a string and the result is concatenated.
"the answer is " + 42; // "the answer is 42" "this is " + true; // "this is true" var a; "a is " + a; // "a is undefined"
In any other case (except for Dates) the operands are converted to numbers and the results are added.
1 + true; // -> 1 + 1 -> 2 null + false; // -> 0 + 0 -> 0
Dates for some reason are converted to strings, and thus the two operands are concatenated.
new Date() + 86400000; // that's not adding one day to date! // that results in "Tue May 19 2009 10:46:30 GMT+020086400000" or something
The comparison operator ==
The first book on javascript that I read was ppk on JavaScript. There I read […] An empty String ” becomes false. All other values become true.
. Of course I had to test this by myself and tried to convert the string “0” to a boolean. How do you know if this converts to true? Compare it! (No, actually not. Don’t repeat my mistake. Read the next part of this series about how to explicitly convert types.) So I did this:
"0" == true; // don't do this
To my surprise this evaluated to false. I even wrote an email to ppk to point out that error in his book, which I find quite embarassing by now.
The reason behind that is the unexpected ruleset of type conversion using the comparison operator. In my case I expected it to convert the string “0” to a boolean, but it did not. Actually, the boolean was converted to a number. Yes, to a number. In the next step “0” was converted to a number as well. Therefore these were the steps taken:
"0" == true; // first step: convert true to a number "0" == 1; // second step: convert "0" to a number 0 == 1; // last step: compare false;
That tought me a lot about javascript.
If you compare two values of the same type using the comparison operator no type conversion is done (although the results sometimes are surprising, I might cover this in an own article).
So it comes down to compare two values of different types. The first rule is: null and undefined are equal.
null == undefined; // true
The second rule is: when in doubt convert to number. If you compare a string and a number, convert the string to a number. If you compare a boolean to something else, convert the boolean to a number. On the other hand, if you compare an object to something else, convert it to a primitive by calling its valueOf method (and if that does not return a primitive call toString) and go on.
The Date object is different of course. Its valueOf normally returns a number, yet in combination with the comparison operator it returns a string representation.
This table shows it all. Note that the comparison operator is commutative, that means x == y and y == x return the same value.