The original
Implicit coercion in Javascript simply means that Javascript tries to force an unexpected value type to be the expected type. So you can pass a string where you want a number, an object where you want a string, and so on, and it will try to convert it to the correct type. This is a Javascript feature best avoided.
3 * "3" / / 9
1 + "2" + 1 / / 121
true + true / / 2
10 - true / / 9
const foo = {
valueOf: () = > 2
}
3 + foo / / 5
4 * foo / / 8
const bar = {
toString: () = > " promise is a boy :)"
}
1 + bar // "1 promise is a boy :)"
4 * [] / / 0
4 * [2] / / 8
4 + [2] 42 "/ /"
4 + [1.2] 41, 2 "/ /"
4 * [1.2] // NaN
"string" ? 4 : 1 / / 4
undefined ? 4 : 1 / / 1
Copy the code
A non-numeric value in a numeric expression
string
Whenever you pass a string as an operand in a numeric expression involving any of the following operators: -, *, /, %, the conversion of the Number is analogous to calling the built-in Number function on the value. This is very simple, any string containing only numeric characters will be converted to its numeric equivalent, but strings containing non-numeric characters will return NaN. The following figure,
3 * "3" / / 3 * 3
3 * Number("3") / / 3 * 3
Number("5") / / 5
Number("1.") / / 1
Number("1.34") / / 1.34
Number("0") / / 0
Number("012") / / 12
Number("1,") // NaN
Number("1 + 1") // NaN
Number("1a") // NaN
Number("one") // NaN
Number("text") // NaN
Copy the code
The + operator
The + operator, unlike other mathematical operators, performs two functions:
- Addition of mathematics
- String conjunction
Instead of converting a string to a number, Javascript converts a number to a string when the string is the operand of the + operator.
// concatenation
1 + "2" / / "12"
1 + "js" // "1js"
// addition
1 + 2 / / 3
1 + 2 + 1 / / 4
//addition, then concatenation
1 + 2 + "1" / / "31"
(1 + 2) + "1" / / "31"
//concatenation all through
1 + "2" + 1 / / "121"
(1 + "2") + 1 / / "121"
Copy the code
object
Most Javascript object conversions usually result in [object object], for example
"name" + {} // "name[object Object]
Copy the code
Every javascript object inherits a toString method, which is called whenever an object is converted to a string. The return value of the toString method is used for operations such as string concatenation and mathematical expressions.
const foo = {}
foo.toString() // [object Object]
const baz = {
toString: () = > "I'm object baz"
}
baz + "!" // "I'm object baz!"
Copy the code
When it is a mathematical expression, Javascript will attempt to convert the return value to a number, if not.
const foo = {
toString: () = > 4
}
2 * foo / / 8
2 / foo / / 0.5
2 + foo / / 6
"four" + foo // "four4"
const baz = {
toString: () = > "four"
}
2 * baz // NaN
2 + baz // 2four
const bar = {
toString: () = > "2"
}
2 + bar / / "22"
2 * bar / / 4
Copy the code
The array object
The inheritance method of toStringArrays is a little different, and it works like join calls arrays with no arguments.
[1.2.3].toString() / / "1, 2, 3"
[1.2.3].join() / / "1, 2, 3"
[].toString() / / ""
[].join() / / ""
"me" + [1.2.3] Me1, 2, 3 "/ /"
4 + [1.2.3] 41, 2, 3 "/ /"
4 * [1.2.3] // NaN
Copy the code
So when you pass an array where you want a string, Javascript concatenates the return value of the toString method with the second operand. If it needs a number, it tries to convert the return value to a number.
4 * [] / / 0
4 / [2] / / 2
//similar to
4 * Number([].toString())
4 * Number("")
4 * 0
//
4 / Number([2].toString())
4 / Number("2")
4 / 2
Copy the code
True, False and “”
Number(true) / / 1
Number(false) / / 0
Number("") / / 0
4 + true / / 5
3 * false / / 0
3 * "" / / 0
3 + "" / / "3"
Copy the code
thevalueOf
methods
You can also define a valueOf method that Javascript uses when you pass an object that requires a string or numeric value.
const foo = {
valueOf: () = > 3
}
3 + foo / / 6
3 * foo / / 9
Copy the code
When both toString and valueOf methods are defined on an object, Javascript uses the valueOf method.
const bar = {
toString: () = > 2.valueOf: () = > 5
}
"sa" + bar // "sa5"
3 * bar / / 15
2 + bar / / 7
Copy the code
The valueOf method applies to objects that should represent numeric values.
const two = new Number(2)
two.valueOf() / / 2
Copy the code
False and true
I really wanted it to be fake and real
Each Javascript value can be forced to be true or false. A cast to true means that the value is true. A cast to a Boolean value false means that the value is false.
There are some values in Javascript that return false values. They are:
- The wrong
- 0
- A null value
- Is not clear
- “”
- NaN
- 0
Everything else is true
if (-1) // truthy
if ("0") // truthy
if ({}) // truthy
Copy the code
The code snippet above is fine, but it is best to be explicit when trying to determine the authenticity of a value. Basically, don’t rely on Javascript’s implicit coercion, even if you think you know them well. Instead of the following code snippet,
const counter = 2
if (counter)
Copy the code
Depending on your requirements, either of the following is preferable
if (counter === 2)
//or
if (typeof counter === "number")
Copy the code
This is because, for example, you define a function that should handle numbers
const add = (number) = > {
if(! number)new Error("Only accepts arguments of type: number")
//your code
}
Copy the code
So if I call add with 0, I always get an unexpected error
add(0) // Error: Only accepts arguments of type: number
//better check
const add = (number) = > {
if (typeofnumber ! = ="number") new Error("Only accepts arguments of type: number")
//your code
}
add(0) // no error
Copy the code
NaN
NaN is a special value that is not equal to itself.
NaN= = =NaN // false
const notANumber = 3 * "a" // NaN
notANumber == notANumber // false
notANumber === notANumber // false
Copy the code
NaN is the only Javascript value that is not equal to itself. Therefore, you can check NaN by comparing it to itself.
if(notANumber ! == notANumber)// true
Copy the code
ECMAScript 6 introduces a way to check NaN, number.isnan
Number.isNaN(NaN) // true
Number.isNaN("name") // false
Copy the code
Watch out for the global isNaN function, which checks to see if it isNaN. For example,
isNaN("name") // true
isNaN("1") // false
Copy the code
IsNaN should avoid using global functions, which work like the following
const coerceThenCheckNaN = (val) = > {
const coercedVal = Number(val)
returncoercedVal ! == coercedVal ?true : false
}
coerceThenCheckNaN("1a") // true
coerceThenCheckNaN("1") // false
coerceThenCheckNaN("as") // true
coerceThenCheckNaN(NaN) // true
coerceThenCheckNaN(10) // false
Copy the code
This is the majority of implicit coercion. If I missed anything, let me know in the comments below, and thanks for reading along the way.