All about types in Javascript - Automatic type conversion

Matthias Reuter's picture

This is the second part of a series "All about types" in Javascript.

  1. The basics - types and general rules of conversion
  2. Automatic type conversion
  3. Explicit type conversion
  4. 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.

Rules of conversion using x == y
type of x type of y result
null undefined true
number string x == Number(y)
boolean any, except for string Number(x) == y
object string or number primitive representation of x == y
any other case false

The -, *, / and % operator

That's easy. When dealing with these operators convert the operands to number.

3 / "3";    // 1
"3" - true; // 2
null * "3"; // 0
"42" % "5"; // 2

The relational operator <

You can either compare strings or numbers. If you try to compare other types, convert the operands to numbers. Even Dates comply with that. Then you have two numbers to compare, and that's easy.

true < 2;                // 1 < 2, true
true < null;             // 1 < 0, false
"3" < 4;                    // 3 < 4, true
new Date() < 1234567890000; // false, if your clock is set correctly
{ valueOf : function () { return 3; }} < 4; // 3 < 4, true

The logical operators && and ||

The logical operators in javascript work on any type, unlike in Java. And unlike in Java, they do not return a boolean value. Still they expect boolean values and if not given two the operands are converted to boolean.

So technically that's a simple case. The implications, however, are immense. If you understand what happens you rose to a higher level of javascript development. If you like you may call yourself a ninja now.

Though the logical operators implicitly convert the operands to boolean (not neccessarily all, depending on the context), not the boolean value is returned but the operand itself.

var a = 0 || "4";
// a is now "4"

This comes in handy when supplying default values. Assume a function that returns the day of a year for a given date. If no date is supplied, the current date is taken:

function getDayOfYear = function (date) {
  date = date || new Date();
  var first = new Date(date.getFullYear(), 0, 1);
  return Math.floor((date - first) / 86400000) + 1;
}

In DOM scripting the logical or operator helps avoid browser incompabilities:

function doSomethingOnClick (event) {
  event = event || window.event;
  var target = event.target || event.srcElement;
}

In line 2 we look if the parameter event has been set (W3C event model) or not (Microsoft event model). In line 3 we get the element the action occured on according to the W3C model or the Microsoft model respectively.

You can use the logical and operator to do null checks before accessing object properties:

function setBackground (element, color) {
  if (element && element.style) {
    element.style.backgroundColor = color;
  }
}

Line 2 is a null check for both element and element.style.

Summary

Automatic type conversion happens in many cases. In most cases it is somewhat logical, in others you either need to know exactly what you're doing or you need to do an explicit type conversion. How to do this is covered in the upcoming third part of this series.

Comments

Better Javascript: Updates on the address book | united-code's picture

[...] greatly if we double check all properties this way. The solution to this - again - lies in the automatic type conversion of Javascript. Both empty strings and undefined convert to [...]

Anonymous's picture

*puts on a beat*

(false != null)
do it yourself... false != null
anyone can do it... false != null
it's simple enough to check.... false != null

*cut beat*

Now, booleans are pseudo-types. They're actually numbers. Given that, logical operations are actually
a || b = (a >= b) ? a : b;
a && b = (a >= b) ? b : a;
!a = (a == 0) ? true : false;

NOTE: Mathwise, null is a number that does not equal zero but holds the equivalent value of zero!

Now... null doesn't actually follow the rules.
given a = null.

a || b = b;
a && b = a;
!a = true;

I believe these are fixed exceptions rather than processed code. use undefined as your "b" comparison to see what I mean.

What does this mean?

The logical operations performed on null are non consistent.

A || B actually translates as

if (a == null) {
return b;
} else {
if (a >= b) {
return a;
} else {
return b;
}
}

so you'll throw out any null variable AND any variable less than or equal to A.

Like 0 or "0" or [0] or -1 or "-1" or [-1]

And thats not including what happens if you pass an object, array, string or function pointer...

In that case anything to the LEFT on an OR operation will be returned, so long that it is not null. and anything to the right on an AND operation will be returned so long that it's not null.

Thats all handy dandy... but if you were SUPPOSE to have a numeric variable there then you're screwed. Javascript is type insensitive!

And all this to avoid one simple comparison.
a = (a == null) ? new a() : a;

or even
a = (a === undefined) ? new a(): a;
if you want to go the extra mile.

But using javascript's type insensitivity to detect if something is null ONLY to save 5 seconds of typing is piss poor programing, and you should know better.

 Vergleiche mit Javascript [Javascript ist Toll!]'s picture

[...] Hier noch ein englischer Artikel der das ganze noch etwas detaillierter erklärt. http://www.united-coders.com/matthias-reuter/all-about-types-part-2 [...]

Tattoo and piercing cincinnati - Ringmaster piercing - Pierc's picture

[...] All about types in Javascript - Automatic type conversion | united 2 Mar 2010. This is the second part of a series "All about types" in.. new Date() < 1234567890000; // false, if your clock is set correctly.united-coders.com/.../all-about-types-in-javascript-automatic-type-conversion - All about types in Javascript - Automatic type conversion | united [...]

Apartment chevalier location serre - Location operates - Loc's picture

[...] All about types in Javascript - Automatic type conversion | united 2 Mar 2010. This is the second part of a series "All about types" in.. new Date() < 1234567890000; // false, if your clock is set correctly.united-coders.com/.../all-about-types-in-javascript-automatic-type-conversion - All about types in Javascript - Automatic type conversion | united [...]