Implicit Coercion
Over the last two blog posts I've taken a deep look into the ToString
, ToNumber
, ToBoolean
, and ToPrimitive
Abstract Operations that govern type conversion as well as different methods of performing Explicit Coercion in JavaScript. It's time to continue this little series with an exploration of Implicit Coercion, which is a touchy subject. A lot of the discussion around JavaScript's shortcomings as a programming language seem rooted in frustrating experiences with Implicit Coercion. Once again, I don't intend to talk about those opinions, and instead I simply want to understand Implicit Coercion as a concept, and how it fits in with Explicit Coercion and the Abstract Operations that make type coercion work the way that it does in JavaScript.
To review one last time, Coercion is the operation of converting a value from one type to another. In JavaScript, coercion always results in either a String
, a Number
, or a Boolean
.
The entire topic of coercion is all about three specific operations:
- Converting non-
String
values toString
values - Converting non-
Number
values toNumber
values - Converting non-
Boolean
values toBoolean
values
The underlying mechanism that makes coercion work in JavaScript is a set of Abstract Operations, specifically ToString
, which handles the conversion of a non-String
primitive to a String
representation, ToNumber
, which handles the conversion of a non-Number
primitive to a Number
representation, ToPrimitive
, which handles the conversion of a complex value (like an Object
) to a primitive representation (so that either ToString
or ToNumber
can further convert them), and ToBoolean
, which defines which value types are "falsy" (i.e., will coerce to false
) or "truthy" (i.e., will coerce to true
).
There are a number of ways that coercion can occur that are generally considered clear and straightforward, and these methods are referred to as Explicit Coercion. The global String()
function and the .toString()
method will convert non-String
values to String
representations. The global Number()
function, the parseInt()
and parseFloat()
functions, and +
and -
unary operators will convert non-Number
values to Number
representations. The global Boolean()
function and the !
unary operator will convert non-Boolean
values to Boolean
representations.
What is Implicit Coercion?
Implicit Coercion is a coercion operation where the coercion seems to occur as a side-effect of some other operation, like a mathematical operation or string concatenation. In these cases, the type coercion often happens "in the background", so to speak, so it may not be as clear as to what value type is being converted to another value type and why.
Implicitly Coercing to a String
Aside from numeric addition operations, the +
operator can be used to concatenate String
s in JavaScript, like so:
var str1 = "hey there ";var str2 = "what's up";
var result = str1 + str2;
console.log(result);// expected result: "hey there what's up"
The +
operator's concatenation operation produces a String
. In this case, it's simply combining the two String
s that are given as its operands. In this example, this is not coercion at all, just the combination of the two operand String
values into one.
However, when the +
operator produces a String
value, but at least one of its operands is a non-String
, then a coercion operation must have occurred, converting that non-String
operand into a String
representation that could then be concatenated. This is how Implicit Coercion comes into play, since the type conversion happens as a side effect of another operation, namely the concatenation operation.
Let's look at this in action:
var str = "hello";var num = 420;
var result = str + num;
console.log(result);// expected result: "hello420"
In this case we use the +
operator with a String
"hello"
as one of its operands and the Number
420
as the other operand. Because one of the operands is a String
, the +
operator will go for a concatenation operation, producing a String
. But before it can do that, it needs to coerce the non-String
operand to a String
representation using the rules laid out in the ToString
Abstract Operation. In this case, because 420
is a Number
, ToString
simply returns a natural String
representation of that Number
, "420"
. Now that the two operands are String
values, the concatenation can occur, producing the result
, the String
"hello420"
.
Because it's a result of the concatenation operation, the coercion of the non-String
operand to a String
representation is said to be an Implicit Coercion. On top of that, the use of the +
operator in this context may be confusing to a developer who is not as familiar with these rules, and expects +
to be strictly an operator used for addition.
Consider another, similar example:
var str = "";var num = 420;
var result = str + num;
console.log(result);// expected result: "420"
console.log(typeof result);// expected result: "string"
In this example we are concatenating an empty String
""
with the Number
420
. 420
gets coerced to a String
representation as in the previous example, and when "420"
gets concatenated with an empty String
, the result is just the String
"420"
. This pattern of the +
operator having an empty String
""
as its operand to coerce the other, non-String
, operand to a String
representation is very, very common, and it's all based on Implicit Coercion. It's worth familiarizing yourself with the pattern, so you know what the developer is trying to do when you run across it in the wild!
It seems straightforward enough that when one of +
's operands is a String
, then +
will do a concatenation operation, and thereby do any necessary coercion of a non-String
value to a String
representation. However, it's not as simple as that. Let's look at another example:
var arr = [4, 2, 0];var num = 100;
var result = arr + num;
console.log(result);// expected result: 4,2,0100
console.log(typeof result);// expected result: "string"
In this example we've given to the +
operator an Array
operand, arr
, with the value [4, 2, 0]
, and a Number
operand, num
, with the value 100
. The result of the operation is the String
"4,2,0100"
. What happened here? Unfortunately, the answer is complicated.
When the +
operator receives a complex value, like an Object
or an Array
, for either of its operands, it abides by the ToPrimitive
Abstract Operation for that value, hoping to produce a simple primitive value that it can then do further work on, either as a Number
that it can do math with or a String
that it can concatenate. This Abstract Operation looks for a [Symbol.toPrimitive]
method, which isn't found here, then for the result of the .valueOf()
method, which in this case just produces the array itself (not a primitive, so not something that the +
operator can use), and then finally falls back to the .toString()
method, which as we now know produces the String
"4,2,0"
.
Since this complex value produced a String
, the +
operator knows it needs to concatenate, so it coerces 100
to its natural String
representation, "100"
, and then concatenates it with "4,2,0"
, producing the result we see here: "4,2,0100"
.
Implicitly coercing to a String
value all centers around the +
operator, and if one of its operands is a String
or its ToPrimitive
algorithm produces a String
, then concatenation will occur, and any non-String
operand values will get coerced to their String
representations in order to allow for that concatenation to happen.
With this understanding in mind, let's look now at how the different types implicitly coerce to String
representations. I will be concatenating with an empty String
""
to make everything as clear as I can.
Concatenating null
with an empty String
produces "null"
:
null + "";// expected result: "null"
Concatenating undefined
with an empty String
produces "undefined"
:
undefined + "";// expected result: "undefined"
Concatenating a Boolean
with an empty String
produces the String
representation of that Boolean
:
true + "";// expected result: "true"
false + "";// expected result: "false"
An Array
with no user-defined .toString()
method will use the generic one that comes from Array.prototype.toString()
, which internally calls the .join()
method:
var arr = ["Joey", "Reyes", "rules"];arr + "";// expected result: "Joey,Reyes,rules"
If both operands are Array
s, then this same coercion using Array.prototype.toString()
will happen for each Array
separately, and their results will get concatenated:
var arr1 = ["Joey", "Reyes", "rules"];var arr2 = ["JavaScript", "drools"];arr1 + arr2;// expected result: "Joey,Reyes,rulesJavaScript,drools"
Function.prototype
also has its own .toString()
method, which generally returns a String
representing the source code of the function. Thus, when you concatenate a Function
and an empty String
you get something like:
function doSomething(a) { return a * a;}
doSomething + "";// expected result: "function doSomething(a) {\n return a * a;\n}"
However, where Symbol.prototype
also has a .toString()
method, you are not permitted to use a string concatenation operation to implicitly coerce the Symbol
to a String
representation:
var sym = Symbol("howdy");
sym + "";// expected result: Uncaught TypeError
Object
s are a bit more complicated. As discussed previously, an Object
will coerce to a String
representation following the algorithm defined in the ToPrimitive
Abstract Operation. First it looks for a [Symbol.toPrimitive]
method on the Object
in question. If [Symbol.toPrimitive]
is found, and it returns a String
, then that String
is what +
will use to concatenate.
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [Symbol.toPrimitive](hint) { return this.b; },};
var str = "";
var result = obj + str;console.log(result);// expected result: "Joey Reyes rules"
If [Symbol.toPrimitive]
is not an available method, then ToPrimitive
will look for a .valueOf()
method:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], valueOf() { return this.b; },};
var str = "";
var result = obj + str;console.log(result);// expected result: "Joey Reyes rules"
If a user-defined .valueOf()
method is not available, then ToPrimitive
will call Object.prototype.valueOf()
. However, this just produces the contents of the Object
itself:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3],};
obj.valueOf();// expected result: {a: 100, b: 'Joey Reyes rules', c: true, d: Array(3)}
Because we need a Primitive and not a complex value, ToPrimitive
then proceeds to look for a .toString()
method:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], toString() { return this.b; },};
var str = "";
var result = obj + str;console.log(result);// expected result: "Joey Reyes rules"
If a defined .toString()
method is not found, it uses the generic .toString()
method from Object.prototype.toString()
, which returns the [[Class]]
property, ultimately outputting the String
"[object Object]"
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3],};
var str = "";
var result = obj + str;console.log(result);// expected result: "[object Object]"
If all of this sounds familiar, it's because this is now the third blog post in a row where I've written out this same exact logic.
In most cases using the [non-string value] + ""
pattern to coerce [non-string value]
to its String
representation counterpart works the same as passing [non-string value]
to the global String()
function. However, you should be aware of one crucial difference: If the Object
in question doesn't have a [Symbol.toPrimitive]
method, then [non-string value] + ""
will call the .valueOf()
method before calling the .toString()
method. The global String()
function on the other hand calls the .toString()
method first. In most cases the result will be the same, but if you have written an Object
and defined your own .valueOf()
and .toString()
methods on that Object
, then you should be aware which method these two coercion approaches will take.
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], e: "JavaScript drools", toString() { return this.b; }, valueOf() { return this.e; },};
var str = "";
obj + str;// expected result: "JavaScript drools"
String(obj);// expected result: "Joey Reyes rules"
At the end of the day, using the +
operator where one of the operands is a String
or results in a String
from the ToPrimitive
abstract operation will result in a String
. If one of +
's operands is a non-String
value and the other is an empty String
, it's effectively the same as passing that non-String
value to the String()
global function (though there is some nuance to be aware of).
Implicitly Coercing to a Number
Let's take a bit of a side quest now to examine some other mathematical operators, specifically -
, *
, /
, and %
.
-
is commonly used for subtraction:
var num1 = 100;var num2 = 10;
var result = num1 - num2;
console.log(result);// expected result: 90
*
is commonly used for multiplication:
var num1 = 100;var num2 = 10;
var result = num1 * num2;
console.log(result);// expected result: 1000
/
is commonly used for division:
var num1 = 100;var num2 = 10;
var result = num1 / num2;
console.log(result);// expected result: 10
%
is commonly used to calculate the division remainder:
var num1 = 100;var num2 = 10;
var result = num1 % num2;
console.log(result);// expected result 0
If either of the operands for any of these operators is a non-Number
value, then the operator will attempt to convert that value to a Number
representation using the ToNumber
Abstract Operation.
null
coerces to 0
:
null - 100;// expected result: -100
undefined
coerces to NaN
:
undefined - 100;// expected result: NaN
true
coerces to 1
and false
coerces to 0
:
true - 100;// expected result: -99
false - 100;// expected result: -100
String
s will coerce to their Number
equivalents if possible...
"420" - 100;// expected result: 320
...otherwise they will coerce to NaN
:
"four hundred twenty" - 100;// expected result: NaN
An Object
will first look for and utilize the [Symbol.toPrimitive]
method with a hint
of number
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], [Symbol.toPrimitive](hint) { console.log(`hint: ${hint}`); // let's see what the hint is return hint === "string" ? `{ b: "${this.b}" }` : this.a; },};
var num = 100;
var result = obj - num;console.log(result);// expected result:// hint: number// 0
If [Symbol.toPrimitive]
isn't available it will look for a .valueOf()
method:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], valueOf() { return 420; },};
var num = 100;
var result = obj - num;console.log(result);// expected result: 320
If a user-defined .valueOf()
method is not available, then ToPrimitive
will call Object.prototype.valueOf()
. This just produces the contents of the Object
itself:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3],};
obj.valueOf();// expected result: {a: 100, b: 'Joey Reyes rules', c: true, d: Array(3)}
Because we need a Primitive and not a complex value, ToPrimitive
then proceeds to look for a .toString()
method:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], toString() { return this.b; },};
var num = 100;
var result = obj - num;console.log(result);// expected result: NaN
If a defined .toString()
method is not found, it uses the generic .toString()
method from Object.prototype.toString()
, which returns the [[Class]]
property, ultimately returning the String
"[object Object]"
. Because this String
is passed to -
, *
, /
, or %
, the result is NaN
:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3],};
var num = 100;
var result = obj - num;console.log(result);// expected result: NaN
For an Array
, the generic Array.prototype.toString()
method internally calls the .join()
method, returning the contents of the Array
separated by commas. If the Array
only has a single element that is either a Number
or a value that can be coerced to a Number
, then we can actually get a meaningful mathematical operation:
var arr = ["420"];
var num = 100;
var result = arr - num;console.log(result);// expected result: 320
However, in all other cases you're likely just going to wind up with NaN
:
var arr = [ "420", "1000", { valueOf() { return 2000; }, },];
var num = 100;
var result = arr - num;console.log(result);// expected result: NaN
Because Function.prototype.valueOf()
just returns the Function
itself, you get NaN
when one of the -
/*
//
/%
's operands is a Function
:
function doSomething(a) { return a * a;}
var num = 100;
var result = doSomething - num;console.log(result);// expected result: NaN
You can, of course, call the Function
, and if that returns a Number
then you're good (although that isn't really coercion, is it?):
function doSomething(a) { return a * a;}
var num = 100;
var result = doSomething(100) - num;console.log(result);// expected result: 9900
As with implicit String
coercion, we are not allowed to implicitly coerce a Symbol
to a Number
:
var sym = Symbol("howdy");
sym - 100;// expected result: Uncaught TypeError
We've focused on the -
, *
, /
, and %
operators for implicit Number
coercion so far, but that's not the whole picture. Let's turn back to the +
operator, which we know will perform concatenation if either of its operands is a String
or coerces to a String
as a result of the ToPrimitive
Abstract Operation. If, on the other hand, the operand is a non-String
primitive that can cleanly coerce to a Number
, then it will do so.
null
coerces to 0
:
null + 100;// expected result: 100
undefined
coerces to NaN
(and this operation will not coerce to a String
):
undefined + 100;// expected result: NaN
true
coerces to 1
and false
coerces to 0
:
true + 100;// expected result: 101
false + 100;// expected result: 100
And lastly, any Object
that coerces to a Number
from a [Symbol.toPrimitive]
, .valueOf()
, or (for some reason) .toString()
method will complete the addition operation:
var obj = { a: 100, b: "Joey Reyes rules", c: true, d: [1, 2, 3], valueOf() { return this.a; },};
var num = 100;
var result = obj + num;console.log(result);// expected result: 200
Implicitly Coercing to a Boolean
We are now left with implicit coercion of non-Boolean
values to Boolean
representations, which happen in 7 specific operations:
- The test condition of an
if
statement. For example,
if (condition) { /* do work here */}
- The test condition (second expression) within the parenthesis of a
for
loop. For example,
for (let counter = 0; counter <= 10; counter += 1) { /* do work here */}
- The test condition of a
while
loop. For example,
while (counter <= 420) { /* do work here */}
- The test condition of a
do...while
loop. For example:
do { /* some work here, always runs at least once */} while (counter <= 420);
- The test condition (first expression) of a ternary expression. For example:
condition ? "condition has been met" : "condition has not been met";
- The left hand operand in the Logical Or
||
operator. For example:
condition1 || condition2;
- The left hand operand in the Logical And
&&
operator. For example:
condition1 && condition2;
Any non-Boolean
values used within these contexts will be implicitly coerced to a Boolean
in order to complete the necessary conditional or logical operation. As you may be able to predict by now, this coercion happens in accordance with the ToBoolean
Abstract Operation, which defines which values types are "falsy" (i.e., will coerce to false
) and which value types are "truthy" (i.e., will coerce to true
).
To review, the "falsy"
values are undefined
, null
, +0
, -0
, NaN
and ""
(empty String
). The "truthy" values are all other values and types.
Let's compare and contrast some of "falsy" and "truthy" values within some of the contexts above.
How about an undefined
value ("falsy") and an empty Array
("truthy") within an if ()
statement:
var undefinedThing;var definedThing = [];
if (undefinedThing) { console.log("I'm never going to run");}// expected result: this condition never passes
if (definedThing) { console.log("hey there, from inside of the if statement");}// expected result: "hey there, from inside of the if statement"
Or a null
value ("falsy") and an Object
("truthy") within a while
Loop:
var nullThing = null;var obj = { counter: 0,};
while (nullThing) { console.log("I'm never going to run");}// expected result: this condition never passes
while (obj.counter < 10) { console.log("counting up!"); obj.counter += 1;}// expected result: ten instances of "counting up!" and obj.counter counts up
Or -0
("falsy") and another Number
, like 420
, within a do...while
loop:
var neg0 = -0;var num = 420;
do { console.log("I always run at least once");} while (neg0);// expected result: one instance of "I always run at least once", and then nothing else
do { console.log("counting down!"); num -= 1;} while (num >= 400);// expected result: 21 instances of "counting down!" and num counts down
Or an empty String
("falsy") and a non-empty String
("truthy") within a ternary expression:
var emptyStr = "";var str = "Joey Reyes rules";
emptyStr ? "String is not empty" : "String is empty";// expected result: "String is empty"
str ? "String is not empty" : "String is empty";// expected result: "String is not empty"
The Logical Or ||
and Logical And &&
operators work a little differently, and perhaps not as one would expect. They each accept two operands, a left hand operand and a right hand operand. If the left hand operand is not already a Boolean
, then the operator will do a ToBoolean
operation to coerce the value to a Boolean
representation.
What happens next depends on the operator.
If the left hand operand coercion results in true
(or the operand is a Boolean
true
to begin with), then the Logical Or ||
operator will return the initial value of the left hand operand:
"hello" || 420;// expected result: "hello"
If the left hand operand coercion results in false
(or the operand is a Boolean
false
to begin with), then the Logical Or ||
operator will return the initial value of the right hand operand:
"" || 420;// expected result: 420
If the left hand operand coercion results in true
(or the operand is a Boolean
true
to begin with), then the Logical And &&
operator will return the initial value of the right hand operand:
"hello" && 420;// expected result: 420
This is the case, even if the right hand operand is a falsy value (or a Boolean
false
):
"hello" && null;// expected result: null
If the left hand operand coercion results in false
(or the operand is a Boolean
false
to begin with), then the Logical And &&
operator will return the initial value of the left hand operand:
"" && 420;// expected result: ""
This may be a bit unexpected, as logical operators in other languages simply return a true
or false
Boolean
in all cases. Here we only get a Boolean
value returned if the initial operand value is itself a Boolean
and the proper logical algorithm returns that Boolean
.
It's a bit confusing. But armed with this understanding, we can now see how for something like:
if ("" || 420) { console.log("Condition met. Joey Reyes rules.");}// expected result: "Condition met. Joey Reyes rules."
What's actually happening are two implicit ToBoolean
coercions. First, to determine which of the two operand values given to the Logical Or ||
operator should get returned, the left hand operand, ""
gets coerced to a Boolean
according to the ToBoolean
Abstract Operation. Because ""
's Boolean
representation is false
, ||
returns the right hand operand, the Number
420
.
From there the conditional statement's test condition is basically:
if (420) { console.log("Condition met. Joey Reyes rules.");}
The if ()
test condition then implicitly coerces the Number
420
, also according to the ToBoolean
Abstract Operation. Because 420
's Boolean
representation is true
, the if ()
test condition is met, so the code block runs.
Summary
Implicit Coercion is a coercion operation where the coercion seems to occur as a side-effect of some other operation, like a mathematical operation or string concatenation.
You can implicitly coerce non-String
values to String
representations as a result of the +
operator's concatenation operation. This happens when at least one of +
's operands is either a String
or a value whose ToPrimitive
Abstract Operation produces a String
. A very common pattern for coercing non-String
values into String
representations is [non-string value] + ""
. For the most part this produces the same results as the explicit String([non-string value])
pattern, but not in all cases.
You can, however, also implicitly coerce non-Number
, non-String
values to Number
representations using the +
operator, as long as that value is a primitive that cleanly coerces to a Number
, or is a complex value that coerces to a Number
as a result of the ToPrimitive
Abstract Operation algorithm. Otherwise, the other mathematical operators (-
, *
, /
, %
) will always try to coerce non-Number
operands to Number
representations in order to complete the mathematical operation. If the non-Number
operand can't be coerced to a Number
, then the mathematical operation will return NaN
(unless the operand is a Symbol
, in which case a TypeError
is thrown).
Finally, there are seven operations where non-Boolean
values get implicitly coerced to Boolean
representations:
- The test condition of an
if
statement - The test condition (second expression) within the parenthesis of a
for
loop - The test condition of a
while
loop - The test condition of a
do...while
loop - The test condition (first expression) of a ternary expression
- The left hand operand in the Logical Or
||
operator - The left hand operand in the Logical And
&&
operator
It's worth noting that the Logical Or and Logical And operators may not return the value that you would normally think they should, and that when used in conjunction with one of the other implicit Boolean
-forcing operations, can actually make more than one implicit Boolean
coercion happen.
Glossary
- Coercion: The operation of converting a value from one type to another. In JavaScript, coercion always results in a scalar primitive value, namely a
String
, aNumber
, or aBoolean
. - Explicit Coercion: A coercion operation where it's very clear from the code what value type is getting converted to another value type and why.
- Implicit Coercion: A coercion operation where the coercion seems to occur as a side-effect of some other operation (like a mathematical operation), and thereby it's less clear what value type is converted to another value type and why.
- Scalar Primitive Value:
- Primitive refers to a data type that is a basic building block of other data types, not one composed of other data types. The six primitive data types in JavaScript are
undefined
,Boolean
,Number
,String
,BigInt
,Symbol
, andnull
. - Scalar refers to a data type that has a single value or unit of data. The scalar data types in JavaScript are
Number
,Boolean
, andString
. Contrast this withnull
orundefined
, whose label is both its type and its value. - A third category would be a Complex, Compound, or Structural value, such as an
Object
(and thereby alsoArray
) or aFunction
. These types are made up of other types.
- Primitive refers to a data type that is a basic building block of other data types, not one composed of other data types. The six primitive data types in JavaScript are
- Abstract Operations: Descriptions of various semantics within JavaScript that help establish norms for operations available across disparate JavaScript implementations.
ToString
: The Abstract Operation that handles conversions of non-String
values toString
representations.ToNumber
: The Abstract Operation that handles conversions of non-Number
values toNumber
representations.ToPrimitive
: The Abstract Operation that handles conversions of complex values to primitive values.ToBoolean
: The Abstract Operation that handles conversions of non-Boolean
values toBoolean
representations.
Sources / Further Reading
- You Don't Know JS: Types & Grammar by Kyle Simpson
- Abstract Operations in ECMAScript 2023 Language Specification by tc39
- Type Conversion Abstract Operations in ECMAScript 2023 Language Specification by tc39
- ToString Abstract Operation in ECMAScript 2023 Language Specification by tc39
- ToNumber Abstract Operation in ECMAScript 2023 Language Specification by tc39
- ToPrimitive Abstract Operation in ECMAScript 2023 Language Specification by tc39
- ToBoolean Abstract Operation in ECMAScript 2023 Language Specification by tc39
- Object to primitive conversion on javascript.info
- Explicit
String
Coercion Operations:- String() Constructor on MDN
- Object.prototype.toString() on MDN
- Number.prototype.toString() on MDN
- Number.prototype.toExponential() on MDN
- Number.prototype.toFixed() on MDN
- Number.prototype.toPrecision() on MDN
- Boolean.prototype.toString() on MDN
- Array.prototype.toString() on MDN
- Function.prototype.toString() on MDN
- Symbol.prototype.toString() on MDN
- Explicit
Number
Coercion Operations: - Explicit
Boolean
Coercion Operations: - Implicit
String
Coercion Operation: - Implicit
Number
Coercion Operations: - Implicit
Boolean
Coercion Operations: