Automatic Type Conversion In The Real World

Share this article

There are a few expressions that are commonly seen in JavaScript, but which some programming purists will tell you are never a good idea. What these expressions share is their reliance on automatic type conversion — a core feature of JavaScript which is both a strength and a weakness, depending on the circumstances and your point of view.

So in this article I’d like to look at two of these expressions in particular, and consider the circumstances in which they are — and are not — a good idea.

The first of these expressions is a simple if() condition:

if(foo)
{
}

The second is a variable assignment with a choice of possible values:

var x = foo || bar;

If the foo and bar in those examples are both boolean values, then the expressions are simple: the first condition passes if foo is true; the second expression assigns foo to x if foo is true, or assigns bar to x if not.

But what if they’re not simple booleans — what if foo is an object, a string, or undefined? What if foo and bar are different data-types? To understand how these expressions will be evaluated, we need to understand how JavaScript automatically converts between data-types.

Automatic Type Conversion

JavaScript is a “loosely typed” language, which means that whenever an operator or statement is expecting a particular data-type, JavaScript will automatically convert the data to that type. The if() statement in the first example expects a boolean value, therefore whatever you define in the brackets will be converted to a boolean. The same is true for while() and do...while() statements.

JavaScript values are often referred to as being “truthy” or “falsey”, according to what the result of such a conversion would be (i.e. true or false). The simplest way to think of it is like this: a value is truthy unless it’s known to be falsey; and in fact there are only six falsey values:

  • false (of course!)
  • undefined
  • null
  • 0 (numeric zero)
  • "" (empty string)
  • NaN (Not A Number)

Notable exceptions are "0" (string zero) and all types of object — which are truthy — and this includes all primitive constructors, which means that new Boolean(false) evaluates to true! (Kinda confusing, but in practice you never need to create primitive values that way.)

Note: comparing two falsey values won’t always produce the result you might expect, for example (null != false) even though both are falsey values. There are some rather complex algorithms that determine how equality evaluations work, and it’s beyond the scope of this article to discuss them. But if you’re interested in the details, have a look at the The Abstract Equality Comparison Algorithm which is part of ECMAScript 5.1.

The Condition Shortcut

The if() example I showed you at the start converts its expression to a boolean, and since objects always evaluate to true while null evaluates to false, we can use a condition like that to test for the existence of DOM elements:

var element = document.getElementById("whatever");
if(element)
{
  //the element exists
}
else
{
  //the element doesn't exist
}

That will always work reliably when dealing with DOM elements, because the DOM specification requires that a non-existent element returns null.

However, other cases are not so clear-cut, like this example:

function doStuff(foo)
{
  if(foo)
  {
    ...
  }
}

Conditions like that are frequently used to mean “if the foo argument is defined”, but there are several cases where that would fail — namely, any cases where foo is a falsey value. So if, for example, it’s boolean false or an empty string, then the conditional code would not be executed, even though foo is defined.

This is what we want instead:

function doStuff(foo)
{
  if(typeof foo != "undefined")
  {
    ...
  }
}

Arguments (and other variables) which have not been defined, have a data-type of "undefined". So we can use the typeof comparator to test the argument’s data-type, and then the condition will always pass if foo is defined at all. The if() expression is still evaluating a boolean, of course, but the boolean it’s evaluating is the result of that typeof expression.

The Assignment Shortcut

The second example I showed you at the start uses a logical operator, to determine which of two values should be assigned to a variable:

var x = foo || bar;

Logical operators do not return a boolean, but they do still expect a boolean, so the conversion and evaluation happens internally. If foo evaluates to true then the value of foo is returned, otherwise the value of bar is returned. This is immensely useful.

This expression is commonly seen in event-handling functions, where it’s used to define an event argument according to the supported model:

element.onclick = function(e)
{
  e = e || window.event;
};

So e is evaluated as a boolean, and that will be truthy (an event object) if the event-argument model is supported, or it will be falsey (undefined) if not; if it’s truthy then e is returned, or if not then window.event is returned.

The same kind of expression is also commonly used to assign event properties, finding the supported property by evaluating each possibility:

var target = e.target || e.srcElement || window;

So each of those references is evaluated in turn (from left to right), and the first to evaluate to true will be returned. The first case handles the standard model, the second is for Internet Explorer, while the third is for Internet Explorer when the event might fire on the window object (which has no srcElement property).

But expressions like this are equally prone to failure, in cases where the truthy-ness of the data isn’t known. For example, another common use-case is to define defaults for optional arguments, but this is not good:

function doStuff(foo)
{
  foo = foo || "default value";
}

Now if you know for sure that foo will always be either a string or undefined, and assuming that an empty string should be treated as undefined, then that expression is safe. But if not, it will need to be re-defined to something more precise, like this for example:

function doStuff(foo)
{
  if(typeof foo != "string")
  {
    foo = "default value";
  }
}

By testing the type against "string" we can handle multiple cases — where foo is undefined, and also where it’s mis-defined as a non-string value. In that case we also allow an empty string to be valid input, but if we wanted to exclude empty strings, we’d have to add a second condition:

function doStuff(foo)
{
  if(typeof foo != "string" || foo == "")
  {
    foo = "default value";
  }
}

There are other, surprisingly subtle cases where this can be a gotcha. For example, we might have a date function that creates a unix timestamp, unless an input timestamp is optionally defined:

function doDateStuff(timestamp)
{
  timestamp = timestamp || new Date().getTime();
}

That would fail if the input is 0 — because zero is a falsey value, but it’s also a valid timestamp.

General Principles

The general lesson to take from all this is simple — think about how type conversion will affect evaluations, and take care not to fall into the gotchas we’ve encountered. With due care and attention, you can still take advantage of automatic type conversion, to shorten conditions and logical expressions wherever it’s appropriate.

It does rather beg the question though — if we know that explicit testing using typeof is always safe, while relying on automatic type conversion sometimes isn’t — then why not just be explicit all the time? Certainly, if the only reason for preferring the shorter syntax, is that it’s quicker to type, then that’s a lazy and sloppy reason.

But the fact is, JavaScript usually runs across a public network, in situations where file size makes a difference. Smaller files are faster loading, and use less bandwidth, and little syntax shortcuts can really add-up.

Taking advantage of shorter expressions is not an optimization as such, it’s just a coding style that makes the best of language features.

Frequently Asked Questions on Automatic Type Conversion

What is automatic type conversion in programming?

Automatic type conversion, also known as type coercion, is a feature in programming languages where the type of an expression is automatically changed to another type. This happens when the compiler encounters a situation where an expression of one data type is used in a context that expects a different data type. The compiler automatically converts the original data type to the expected data type to avoid any potential errors. This feature is common in languages like JavaScript and Python.

How does automatic type conversion work in Java?

In Java, automatic type conversion occurs when two data types are mixed in an operation. Java automatically converts the data type of a smaller size to the data type of a larger size. For instance, if an integer and a double are used in an operation, Java will automatically convert the integer to a double to ensure precision.

What are the rules for automatic type conversion in JavaScript?

JavaScript follows certain rules for automatic type conversion. When mathematical operations are performed, JavaScript tries to convert non-numbers to numbers. For logical operations, it tries to convert values to boolean. For string operations, it converts values to strings. However, JavaScript’s automatic type conversion can sometimes lead to unexpected results, so it’s important to understand these rules.

What is the difference between implicit and explicit type conversion?

Implicit type conversion is when the compiler automatically changes one data type into another without the programmer’s intervention. This is also known as automatic type conversion. On the other hand, explicit type conversion is when the programmer manually changes the data type of an expression using type-casting methods. This gives the programmer more control over the conversion process.

Can automatic type conversion lead to errors?

Yes, automatic type conversion can sometimes lead to errors or unexpected results. This is especially true in languages like JavaScript, where the rules for type conversion can be complex. For instance, adding a number and a string in JavaScript results in a string, which can be unexpected. Therefore, it’s important to understand how automatic type conversion works in your programming language of choice.

How can I control type conversion in my code?

You can control type conversion in your code by using explicit type conversion or type-casting. This allows you to manually specify the data type you want an expression to be converted to. Different programming languages have different methods for explicit type conversion, so it’s important to understand the syntax and rules of your specific language.

What is the role of automatic type conversion in data types and variables?

Automatic type conversion plays a crucial role in handling data types and variables in programming. It allows for smoother operations between different data types, ensuring that the program runs without any type-related errors. However, it’s important for programmers to understand how their language handles type conversion to avoid unexpected results.

How does automatic type conversion affect the performance of a program?

Automatic type conversion can sometimes affect the performance of a program. This is because the process of converting one data type to another can take up processing time. However, in most cases, the impact on performance is negligible.

Can automatic type conversion cause a loss of data?

Yes, automatic type conversion can sometimes cause a loss of data. This is especially true when converting from a larger data type to a smaller one, as the smaller data type may not be able to hold all the data from the larger one. This is known as a narrowing conversion and can lead to data loss.

How can I avoid problems with automatic type conversion?

The best way to avoid problems with automatic type conversion is to understand how your programming language handles it. This includes knowing the rules for type conversion and how to use explicit type conversion when necessary. Additionally, always testing your code thoroughly can help catch any unexpected results from type conversion.

James EdwardsJames Edwards
View Author

James is a freelance web developer based in the UK, specialising in JavaScript application development and building accessible websites. With more than a decade's professional experience, he is a published author, a frequent blogger and speaker, and an outspoken advocate of standards-based development.

data typesIntermediatejavascriptshorthand syntax
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week