Coercion
Type coercion is the automatic (or implicit) conversion of values from one data type to another.
Essential:
github.com/getify/You-Dont-Know-JS
Description:
As previously introduced, type coercion refers to the automatic conversion of values from one data type to another, typically performed during operations or comparisons involving different data types (such as strings to numbers, for instance). By using Type Coercion, JavaScript attempts to make the data types compatible to complete the operation or comparison.
Table of Contents
1. Introduction
A type can be converted in two different ways:
Description | |
---|---|
Type casting | Explicitly converting a value from one type to another. Occurs in statically typed languages at compile time. TypeScript example: const myVar = otherVar as string . |
Coercion | Occurs in dynamically typed languages, like JavaScript, at runtime. It can happen in 2 different ways: |
▪ Explicit: the intent is to obviously convert a value from one type to another. | |
▪ Implicit: type conversion occurs as a side-effect of some operation. |
Let’s see some examples:
Example:
example1.js
-----------
const a = 42;
// Explicit coercion.
const c = String(a);
// Implicit coercion.
const b = a + "";
example2.js
-----------
// In explicit coercion, the number() function converts
// a value to its numeric representation.
const stringNumber = "42";
const number = Number(stringNumber);
console.log(number); // Output: 42 (a number)
// However, when performing arithmetic operations
// involving strings and numbers, JavaScript converts
// the string to a number (implicit coercion):
var num = 42;
var result = num + "10";
console.log(result); // Output: "4210" (a string)
Note: Whenever coercion occurs, 1 or more internal operations, known as abstract operations, are performed. It always results in a primitive.
Metaphor time:Coercion is somehow similar to translating words from one language to a similar one, like Spanish and Italian. If we were to translate the word ”noche” (night) to Italian, as translators, we would look at all the available Italian words until we could find the one best matching the Spanish word’s meaning: in this case, ”notte“.
In JavaScript, the translator would be the engine, the word, a value, and the languages, JavaScript’s types.
Now, imagine that the engine needs to coerce a value from a string
to a boolean
. The engine would look at
the available “words” (values) in the boolean
“language” (type). Sadly, in this case, there are only two options:
true
or false
, and whichever is selected, a lot of the string’s meaning would be lost in translation, as it
happens too in our own adaptations.
Explicit Coercion
To explicitly coerce a value to a string, number, or boolean, remember to use the built-in native contructors.
In this case, the new
keyword isn’t used, so an object wrapper isn’t created.
Example:
index.js
--------
const a = 1;
const b = String(a);
const c = "1";
const d = Number(c);
const e = "1";
const f = Boolean(c);
// The following constructors can coerce any value
// to a primitive based on the rules of the abstract
// operations:
// ToString
// ToNumber
// ToBoolean
2. ToString
The ToString
abstract operation rules are:
▪ null
becomes ”null"
▪ undefined
becomes "undefined"
▪ true
becomes "true"
▪ number: 1
becomes "1"
.
Example:
index.js
--------
// Very small or large numbers become their exponent form:
const a = 1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
const aStr = a.toString();
// Seven times three digits => 21 digits
console.log(aStr)
// Output: 1.07e+21
index.js
--------
/*
Object values have their own toString() method.
If you implicitly coerce an object, its toString()
will automatically be called:
*/
const obj = [1,2];
// Explicit.
console.log(obj.toString()) // Output: 1,2
// Implicit.
// If either operand to '+' is a string, the operation will be
// string concatenation:
console.log(obj + "") // Output: 1,2
3. ToNumber
The ToNumber
abstract operation rules are:
▪ true
becomes 1
▪ false
becomes 0
▪ undefined
becomes NaN
▪ null
becomes 0
▪ string: "1"
becomes 1
, "a"
becomes NaN
To coerce an Object
value:
Step | Description |
---|---|
1. | The ToPrimitive() abstract operation will check if the object has a valueOf() method. |
▪ If it exists and it returns a primitive value, that value will be used. | |
▪ If it doesn’t exist, but toString() does, its return value will be used. | |
▪ If neither exist or don’t return a primitive, a TypeError is thrown. | |
2. | The primitive value will be coerced as per the ToNumber rules above. |
Example:
index.js
--------
const objA = {
valueOf: function(){
return 1;
}
};
const objB = {
toString: function(){
return "1";
}
};
const objC = [4,2];
objC.toString = function(){
return this.join( "" );
};
console.log(Number(objA)) // Output: 1
console.log(Number(objB)) // Output: 1
console.log(Number(objC)) // Output: 42
console.log(Number([])) // Output: 0
console.log(Number(["abc"])) // Output: NaN
parseInt
parseInt(..)
can be used to get a numeric value out of a string containing non-numeric characters. It parses
left-to-right and stops when a non-numeric value is found.
const a = “42px”; | Outputs |
---|---|
console.log(Number(a)); // Output: NaN | |
console.log(parseInt(a)); // Output: 42 |
4. ToBoolean
The ToBoolean
abstract operation rules are:
▪ undefined
becomes false
▪ null
becomes false
▪ +0
, -0
, and NaN
becomee false
▪ ""
becomes false
▪ all other values become true
var myVar = 1; | Outputs |
---|---|
console.log(Boolean(myVar)); // Output: true | |
console.log(!!myVar); // Output: true |
Implicit Coercion
Expression operations that are implicitly coerced to a boolean:
▪ The test expression in an if (..)
statement.
▪ The test expression (2nd clause) in a for ( .. ; .. ; .. )
header.
▪ The test expression in while (..)
and do..while(..)
loops.
▪ The test expression (1st clause) in a ? : ternary expression.
▪ The left-hand operand to the ||
and &&
operators.
5. Equality
When comparing 2 values for equality, commonly used operators are:
▪ loose equality: ==
▪ strict equality: ===
Example:
index.js
--------
/*
Remember something crucial:
Loose allows coercion.
Strict doesn't.
*/
// Examples:
const a = 42;
const b = "42";
console.log(a == b);
console.log(a === b);
// Outputs:
// true
// false
6. Documentation
If you found this useful, please refer You don’t know JavaScript’s Chapter 4: Coercion - and don’t forget to have a look at these useful resources as well: