javascript
JavaScript Type Coercion
Type coercion is the automatic or implicit conversion of values from one data type to another. Understanding this is crucial for avoiding bugs.
What is Type Coercion?
JavaScript automatically converts types when needed:
javascript
// Number + String = String
console.log(5 + '5'); // '55' (number becomes string)
// String - Number = Number
console.log('10' - 5); // 5 (string becomes number)
// Boolean to Number
console.log(true + 1); // 2 (true becomes 1)
console.log(false + 1); // 1 (false becomes 0)
Implicit vs Explicit Coercion
Implicit Coercion
JavaScript automatically converts types:
javascript
let result1 = '5' * 2; // 10 (string to number)
let result2 = '5' - 2; // 3 (string to number)
let result3 = '5' + 2; // '52' (number to string)
let result4 = !'hello'; // false (string to boolean)
Explicit Coercion
You manually convert types:
javascript
// To Number
let num1 = Number('42'); // 42
let num2 = parseInt('42px'); // 42
let num3 = parseFloat('3.14'); // 3.14
let num4 = +'42'; // 42 (unary plus)
// To String
let str1 = String(42); // '42'
let str2 = (42).toString(); // '42'
let str3 = 42 + ''; // '42'
// To Boolean
let bool1 = Boolean(1); // true
let bool2 = Boolean(0); // false
let bool3 = !!1; // true (double NOT)
String Coercion
When using + with a string, everything becomes a string:
javascript
console.log('5' + 5); // '55'
console.log('Hello' + true); // 'Hellotrue'
console.log('Value: ' + null); // 'Value: null'
console.log('Sum: ' + (2+3)); // 'Sum: 5'
// Template literals always convert to string
console.log(`Result: ${5 + 5}`); // 'Result: 10'
Number Coercion
Mathematical operators (except +) convert to numbers:
javascript
console.log('10' - 5); // 5
console.log('10' * 2); // 20
console.log('10' / 2); // 5
console.log('10' % 3); // 1
// Unary plus converts to number
console.log(+'42'); // 42
console.log(+'3.14'); // 3.14
console.log(+'hello'); // NaN
Boolean Coercion
Used in conditions (if, while, etc.):
Falsy Values
These values convert to false:
javascript
Boolean(false) // false
Boolean(0) // false
Boolean(-0) // false
Boolean('') // false (empty string)
Boolean(null) // false
Boolean(undefined) // false
Boolean(NaN) // false
Truthy Values
Everything else converts to true:
javascript
Boolean(true) // true
Boolean(1) // true
Boolean(-1) // true
Boolean('hello') // true
Boolean('0') // true (non-empty string)
Boolean([]) // true (empty array)
Boolean({}) // true (empty object)
Boolean(function(){}) // true
In Conditions
javascript
if ('hello') {
console.log('Truthy!'); // Executes
}
if (0) {
console.log('Truthy!'); // Doesn't execute
}
// Common pattern
let username = userInput || 'Guest'; // Default if falsy
Equality Coercion
Loose Equality (==)
Performs type coercion:
javascript
console.log(5 == '5'); // true (string to number)
console.log(true == 1); // true (boolean to number)
console.log(false == 0); // true
console.log(null == undefined); // true
console.log('' == 0); // true
console.log('0' == 0); // true
Strict Equality (===)
No type coercion:
javascript
console.log(5 === '5'); // false (different types)
console.log(true === 1); // false
console.log(null === undefined); // false
console.log('' === 0); // false
Always use === and !==!
Common Coercion Pitfalls
The + Operator Trap
javascript
console.log(1 + 2 + '3'); // '33' (not '123')
console.log('1' + 2 + 3); // '123' (not '6')
console.log(1 + 2 + 3); // 6
// Explanation:
// 1 + 2 + '3' → 3 + '3' → '33'
// '1' + 2 + 3 → '12' + 3 → '123'
Array Coercion
javascript
console.log([1, 2] + [3, 4]); // '1,23,4'
console.log([] + []); // ''
console.log([] + {}); // '[object Object]'
console.log({} + []); // '[object Object]'
NaN Comparisons
javascript
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
// Check for NaN
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true (preferred)
null and undefined
javascript
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(null == 0); // false
console.log(null >= 0); // true (quirk!)
console.log(null > 0); // false
Type Conversion Functions
Number()
javascript
Number('42'); // 42
Number('3.14'); // 3.14
Number(''); // 0
Number(' '); // 0
Number('hello'); // NaN
Number(true); // 1
Number(false); // 0
Number(null); // 0
Number(undefined); // NaN
parseInt() and parseFloat()
javascript
parseInt('42'); // 42
parseInt('42px'); // 42 (stops at non-digit)
parseInt('3.14'); // 3 (no decimals)
parseFloat('3.14'); // 3.14
parseFloat('3.14px'); // 3.14
// With radix (base)
parseInt('10', 10); // 10 (decimal)
parseInt('10', 2); // 2 (binary)
parseInt('FF', 16); // 255 (hexadecimal)
String()
javascript
String(42); // '42'
String(true); // 'true'
String(null); // 'null'
String(undefined); // 'undefined'
String([1, 2, 3]); // '1,2,3'
String({a: 1}); // '[object Object]'
Boolean()
javascript
Boolean(1); // true
Boolean(0); // false
Boolean('hello'); // true
Boolean(''); // false
Boolean(null); // false
Boolean(undefined); // false
Boolean([]); // true
Boolean({}); // true
Complete Example
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Type Coercion Demo</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.demo {
background: #f5f5f5;
padding: 15px;
margin: 15px 0;
border-radius: 5px;
}
button {
background: #3498db;
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background: #2980b9;
}
.output {
background: white;
padding: 10px;
margin-top: 10px;
border-radius: 3px;
font-family: monospace;
}
.true { color: green; }
.false { color: red; }
</style>
</head>
<body>
<h1>JavaScript Type Coercion</h1>
<div class="demo">
<h2>String Coercion</h2>
<button onclick="stringCoercion()">Run Demo</button>
<div id="string-output" class="output"></div>
</div>
<div class="demo">
<h2>Number Coercion</h2>
<button onclick="numberCoercion()">Run Demo</button>
<div id="number-output" class="output"></div>
</div>
<div class="demo">
<h2>Boolean Coercion</h2>
<button onclick="booleanCoercion()">Run Demo</button>
<div id="boolean-output" class="output"></div>
</div>
<div class="demo">
<h2>Equality Comparison</h2>
<button onclick="equalityDemo()">Run Demo</button>
<div id="equality-output" class="output"></div>
</div>
<div class="demo">
<h2>Interactive Converter</h2>
<input type="text" id="input" placeholder="Enter a value" value="42">
<button onclick="convertValue()">Convert</button>
<div id="convert-output" class="output"></div>
</div>
<script>
function stringCoercion() {
let output = `
'5' + 5 = ${'5' + 5}<br>
'5' + true = ${'5' + true}<br>
'Hello' + null = ${'Hello' + null}<br>
'Value: ' + undefined = ${'Value: ' + undefined}<br>
[1,2,3] + '' = ${[1,2,3] + ''}<br>
`;
document.getElementById('string-output').innerHTML = output;
}
function numberCoercion() {
let output = `
'10' - 5 = ${'10' - 5}<br>
'10' * 2 = ${'10' * 2}<br>
'10' / 2 = ${'10' / 2}<br>
+'42' = ${+'42'}<br>
+'hello' = ${+'hello'}<br>
true + 1 = ${true + 1}<br>
false + 1 = ${false + 1}<br>
`;
document.getElementById('number-output').innerHTML = output;
}
function booleanCoercion() {
let values = [
['false', false],
['0', 0],
['""', ''],
['null', null],
['undefined', undefined],
['NaN', NaN],
['true', true],
['1', 1],
['"hello"', 'hello'],
['[]', []],
['{}', {}]
];
let output = '<strong>Falsy values:</strong><br>';
values.slice(0, 6).forEach(([label, value]) => {
output += `Boolean(${label}) = <span class="false">${Boolean(value)}</span><br>`;
});
output += '<br><strong>Truthy values:</strong><br>';
values.slice(6).forEach(([label, value]) => {
output += `Boolean(${label}) = <span class="true">${Boolean(value)}</span><br>`;
});
document.getElementById('boolean-output').innerHTML = output;
}
function equalityDemo() {
let comparisons = [
['5 == "5"', 5 == '5'],
['5 === "5"', 5 === '5'],
['true == 1', true == 1],
['true === 1', true === 1],
['null == undefined', null == undefined],
['null === undefined', null === undefined],
['"" == 0', '' == 0],
['"" === 0', '' === 0]
];
let output = '';
comparisons.forEach(([expr, result]) => {
let className = result ? 'true' : 'false';
output += `${expr} = <span class="${className}">${result}</span><br>`;
});
document.getElementById('equality-output').innerHTML = output;
}
function convertValue() {
let input = document.getElementById('input').value;
let output = `
<strong>Original:</strong> "${input}" (${typeof input})<br><br>
<strong>To Number:</strong> ${Number(input)} (${typeof Number(input)})<br>
<strong>parseInt:</strong> ${parseInt(input)}<br>
<strong>parseFloat:</strong> ${parseFloat(input)}<br><br>
<strong>To String:</strong> "${String(input)}"<br><br>
<strong>To Boolean:</strong> ${Boolean(input)}<br>
<strong>Is Truthy:</strong> ${!!input}<br>
`;
document.getElementById('convert-output').innerHTML = output;
}
</script>
</body>
</html>
Preview
Best Practices
- Use strict equality (
===) - Avoid unexpected coercion - Be explicit with conversions - Use
Number(),String(),Boolean() - Understand falsy values - Know what evaluates to false
- Avoid
==with null/undefined - Use===or explicit checks - Use
Number.isNaN()- More reliable thanisNaN() - Be careful with
+- It concatenates with strings