JavaScript Tutorial: Coercion and
‘Typing’
[this page | pdf | back links]
Introduction
Coercion and
associated ‘typing’ concepts are some of the subtler aspects of JavaScript.
They can result in code that appears to exhibit counterintuitive behaviour. In
this page, we summarise some of the complexities involved and their
implications for software development.
Variable types
Most programming
languages include the concept of variables and types that such variables can
exhibit. For example, string variables (text) are usually differentiated from
numerical variables (numbers), since the sorts of manipulations that can
typically be applied to strings differ from the ones that can typically be
applied to numbers.
JavaScript has 5
primitive data types as set out below, as well as some other types, such as
objects:
Data type
|
Purpose
|
number
|
Numbers
|
string
|
Strings
|
boolean
|
True / False
|
null
|
Empty values
|
undefined
|
Variable declared but
not yet assigned a value
|
Weakly typed versus strongly typed software languages
Some (object orientated)
programming languages require the software developer to specify what type a
variable can take and then the variable is required to stay of that type. These
are called ‘strongly typed’ languages. JavaScript adopts a different
approach; its variables are ‘weakly typed’. Their type can change part
way through software execution. For example, the following statements could be
included in JavaScript without throwing an error, and when executed would leave
x equal to “hello”.
var x =
14; x="hello";
Even languages that are
mostly strongly typed may possess ‘variant’ types (e.g. VisualBasic) which can
in effect change their underlying type as execution progresses. In such
languages, variables may be defaulted to have these types if no other type is
specified when they are declared. Such programming languages often have means
of forcing developers to specify the type that a variable takes (even if just
that it is a ‘variant’), e.g. the option
explicit command in VisualBasic, since doing so can lead to more robust
code.
Some commentators view
strong typing and weak typing as synonymous with compiled versus interpreted
computer language. Classically, a compiled language is one in which the
software is converted into a machine-code executable before running, whilst an
interpreted language is one in which the software statements are analysed and
executed ‘on-the-fly’ as the program executes. Machine code generally only
functions on primitive data types so ultimately requires some form of strong
typing. However, nowadays the previous gulf between compiled and interpreted
languages has declined, with e.g. ‘just-in-time’ compilation and other clever
compiling / interpreting techniques. The concept of a ‘variant’ type, an object
that includes as one of its properties the type of data that it currently
represents, also diminishes the difference between these two language types.
Type coercion
If you apply operators
to variables (or values) that do not immediately make sense with such
operators, e.g. trying to add a string to a number, then JavaScript will
typically try to make sense of the expression by carrying out type coercions.
These involve converting the type of one or more expression components into new
types that do make sense in the context of the operator.
Potentially counterintuitive behaviours
The weak typing used in
JavaScript can lead to potentially counterintuitive behaviours or errors, since
the type coercion carried out by JavaScript may not always be as the developer
expects. Conversely, it also sometimes makes for simpler code. This is because
some expressions that might otherwise not be expected to return meaningful
answers do so in ways that can be helpful to program logic.
Examples of potentially
counterintuitive behaviours include ones where text can be interpreted as
numbers and vice versa. For example, if either of the parameters to which a + operator is applied is a string then
the other will where necessary be coerced to a string. The exact result of an
expression can then depend on the order in which the operations are applied.
This depends on the precedence given to different operators, see here. For
example:
var x = 1 + 2 + "5";
var y = (1 + 2) + "5";
var z = 1 + (2 + "5");
result in x = "35",
y = "35" and z
= "125"
EXAMPLE:
HTML USED IN THIS EXAMPLE:
<!DOCTYPE html>
<html> <!-- Copyright (c) Nematrian Limited 2018 -->
<head>
<style>
table,th,tr,td {border: 1px solid black; border-collapse: collapse;}
</style>
</head>
<body>
<table>
<tr><th>Expression</th><th>Outcome</th></tr>
<tr><td><code id="text1"></code></td>
<td><code id="result1"></code></td></tr>
<tr><td><code id="text2"></code></td>
<td><code id="result2"></code></td></tr>
<tr><td><code id="text3"></code></td>
<td><code id="result3"></code></td></tr>
<tr><td><code id="text4"></code></td>
<td><code id="result4"></code></td></tr>
</table>
<script>
document.getElementById("text1").innerHTML='1+2+"5"';
var e1 = 1+2+"5";
document.getElementById("result1").innerHTML=e1;
document.getElementById("text2").innerHTML='(1+2)+"5"';
var e2 = (1+2)+"5";
document.getElementById("result2").innerHTML=e2;
document.getElementById("text3").innerHTML='1+(2+"5")';
var e3 = 1+(2+"5");
document.getElementById("result3").innerHTML=e3;
document.getElementById("text4").innerHTML='("0">-1)';
var e4 = ("0">-1);
document.getElementById("result3").innerHTML=e4;
</script>
</body>
</html>
|
NAVIGATION LINKS
Contents | Prev | Next | JavaScript Operators