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:

  1. Addition of mathematics
  2. 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

thevalueOfmethods

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:

  1. The wrong
  2. 0
  3. A null value
  4. Is not clear
  5. “”
  6. NaN
  7. 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.