你需要了解的关于 JavaScript 隐式强制转换的知识

2025-06-07

你需要了解的关于 JavaScript 隐式强制转换的知识

JavaScript 的隐式强制类型转换是指 JavaScript 尝试将一个非预期的值类型强制转换为预期的类型。因此,你可以将一个字符串传递给 JavaScript 期望的数字类型,将一个对象传递给 JavaScript 期望的字符串类型等等,JavaScript 都会尝试将其转换为正确的类型。这是一个最好避免使用的 JavaScript 特性。

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
Enter fullscreen mode Exit fullscreen mode

数值表达式中的非数字值

字符串

每当您将字符串作为操作数传递到涉及以下任一运算符的数字表达式中时:-, *, /, %,数字的转换过程类似于Number对该值调用内置函数。这非常简单,任何仅包含数字字符的字符串都将转换为其对应的数字,但包含非数字字符的字符串将返回NaN。如下图所示,

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
Enter fullscreen mode Exit fullscreen mode

+ 运算符的情况

+ 运算符与其他数学运算符不同,它执行两项功能:

  1. 数学加法
  2. 字符串连接

当字符串作为 + 运算符的操作数时,Javascript 不会将字符串转换为数字,而是将数字转换为字符串。


// 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"
Enter fullscreen mode Exit fullscreen mode

对象

大多数 JavaScript 对象转换通常会导致[object Object],例如

"name" + {} // "name[object Object]
Enter fullscreen mode Exit fullscreen mode

每个 JavaScript 对象都会继承一个toString方法,当需要将对象转换为字符串时,就会调用该方法。该toString方法的返回值可用于诸如字符串连接和数学表达式之类的操作。

const foo = {}
foo.toString() // [object Object]

const baz = {
  toString: () => "I'm object baz"
}

baz + "!" // "I'm object baz!"
Enter fullscreen mode Exit fullscreen mode

如果它是一个数学表达式,那么 Javascript 将尝试将返回值转换为数字,如果不是的话。

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
Enter fullscreen mode Exit fullscreen mode

数组对象

数组的继承toString方法工作略有不同,其工作方式类似于调用join不带任何参数的数组方法。

[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
Enter fullscreen mode Exit fullscreen mode

因此,当你传递一个需要字符串的数组时,JavaScript 会将toString方法的返回值与第二个操作数连接起来。如果它需要数字,它会尝试将返回值转换为数字。

4 * [] // 0
4 / [2] // 2

//similar to
4 * Number([].toString())
4 * Number("")
4 * 0

//

4 / Number([2].toString())
4 / Number("2")
4 / 2
Enter fullscreen mode Exit fullscreen mode

真、假和“”

Number(true) // 1
Number(false) // 0
Number("") // 0

4 + true // 5
3 * false // 0
3 * "" // 0
3 + "" // "3"
Enter fullscreen mode Exit fullscreen mode

方法valueOf

还可以定义一种valueOf方法,每当您传递一个需要字符串或数字值的对象时,Javascript 都会使用该方法。


const foo = {
  valueOf: () => 3
}

3 + foo // 6
3 * foo // 9
Enter fullscreen mode Exit fullscreen mode

当在对象上同时定义toString和方法时,Javascript将使用方法。valueOfvalueOf

const bar = {
  toString: () => 2,
  valueOf: () => 5
}

"sa" + bar // "sa5"
3 * bar // 15
2 + bar // 7
Enter fullscreen mode Exit fullscreen mode

valueOf 方法适用于表示数值的对象。

const two = new Number(2)

two.valueOf() // 2
Enter fullscreen mode Exit fullscreen mode

Falsy 和 Truthy

我真的很想让它变得虚假和可信

每个 JavaScript 值都可以强制转换为 true 或 false。强制转换为 booleantrue表示该值为真。强制转换为 booleanfalse表示该值为假。

Javascript 中有一些值会返回假值,它们是:

  1. 错误的
  2. 0
  3. 无效的
  4. 不明确的
  5. “”
  6. -0

其他一切都是真实的,

if (-1) // truthy
if ("0") // truthy
if ({}) // truthy
Enter fullscreen mode Exit fullscreen mode

上面的代码片段没问题,但在尝试判断值的真假时,最好使用明确的表达方式。总之,不要依赖 JavaScript 的隐式强制转换,即使你觉得自己非常了解它们。
与其使用下面的代码片段,不如使用:

const counter = 2

if (counter)
Enter fullscreen mode Exit fullscreen mode

根据您的要求,以下任何一种做法都是更好的做法

if (counter === 2)

//or

if (typeof counter === "number")
Enter fullscreen mode Exit fullscreen mode

这是因为,例如,你定义了一个应该处理数字的函数


const add = (number) => {
  if (!number) new Error("Only accepts arguments of type: number")
  //your code
}
Enter fullscreen mode Exit fullscreen mode

因此,如果我用 0 调用 add 函数,总会得到一个意外的错误

add(0) // Error: Only accepts arguments of type: number

//better check

const add = (number) => {
  if (typeof number !== "number") new Error("Only accepts arguments of type: number")
  //your code
}

add(0) // no error

Enter fullscreen mode Exit fullscreen mode

NaN是不等于其自身的特殊数值。

NaN === NaN // false

const notANumber = 3 * "a" // NaN

notANumber == notANumber // false
notANumber === notANumber // false
Enter fullscreen mode Exit fullscreen mode

NaN是唯一一个不等于其自身的 JavaScript 值。因此,你可以NaN通过将其与自身进行比较来检查。

if (notANumber !== notANumber) // true
Enter fullscreen mode Exit fullscreen mode

ECMAScript 6 引入了一种检查 NaN 的方法,Number.isNaN

Number.isNaN(NaN) // true
Number.isNaN("name") // false
Enter fullscreen mode Exit fullscreen mode

小心全局isNaN函数,它会在检查参数是否为 之前尝试强制转换NaN。例如,

isNaN("name") // true
isNaN("1") // false
Enter fullscreen mode Exit fullscreen mode

应避免使用全局isNaN函数,其工作方式类似于下面的函数

const coerceThenCheckNaN = (val) => {
  const coercedVal = Number(val)
  return coercedVal !== coercedVal ? true : false
}

coerceThenCheckNaN("1a") // true
coerceThenCheckNaN("1") // false
coerceThenCheckNaN("as") // true
coerceThenCheckNaN(NaN) // true
coerceThenCheckNaN(10) // false
Enter fullscreen mode Exit fullscreen mode

这就是隐式强制转换的大部分内容。如果我遗漏了什么,请在下面的评论区留言,感谢你一直阅读。

文章来源:https://dev.to/promisetochi/what-you-need-to-know-about-javascripts-implicit-coercion-e23
PREV
CSS 变量速查表简介声明示例用例继承默认(后备)值无效值动态使用(JavaScript)后续内容进一步阅读
NEXT
如何在 git 中将提交移动到另一个分支