一文搞懂 JavaScript 数据类型转换(显式 & 隐式全解析)

1、为什么 JS 会有数据类型转换?

先从一个最本质的特点说起 👇

(1) JavaScript 是一门「动态类型语言」

js 复制代码
var i = 1;
i = "zhangsan";
console.log(i);

在 JS 中:

  • 变量没有固定类型
  • 类型是在运行时才确定的

这和 Java / TypeScript 完全不同。

(2) 运算符「有类型预期」

虽然变量没有类型,但运算符是有要求的 。虽然是两个字符串相减,但是依然得到数值 1,原因就在于 JavaScript 将运算子自动转为了数值。

所以接下来就来看一下 JavaScript 中如何进行数据类型转换。

js 复制代码
'4' - '3' // 1

减法运算符期望的是「数字」,于是 JS 会在背后偷偷做一件事:

js 复制代码
'4' → 4
'3' → 3

这就是数据类型转换存在的根本原因


2、显式转换(你自己动手)

强制转换主要指使用Number()String()Boolean()三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。

2.1 Number():把一切变成数字

(1)原始类型

原始类型值的转换规则如下:

js 复制代码
Number('')        // 0
Number('123')     // 123
Number('zhangsan')  // NaN
Number('123?')    // NaN

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

Number(undefined) // NaN
Number(null)      // 0

⚠️ 注意:Number() 非常严格parseInt能转多少转多少,Number不纯就直接 NaN

js 复制代码
parseInt('123abc') // 123
Number('123abc')   // NaN

(2)对象转换规则(重点)

简单的规则是,Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。

js 复制代码
Number({n: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([6]) // 6

内部其实走了三步规则

  1. 先调用对象自身的 valueOf()方法。如果返回原始类型的值,则直接对该值使用Number函数,不在进行后续操作。
  2. 如果valueOf方法返回的还是对象,则改为调用对象的toString方法。如果toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续操作。
  3. 如果toString方法返回的仍是对象,就报错。
js 复制代码
var obj = { name: 'zhangsan' };
obj.valueOf();   // { name: 'zhangsan' }
obj.toString();  // "[object Object]"
Number(obj);     // NaN

// 等价于
if(typeof obj.valueOf() === 'object') {
   Number(obj.toString());
} else {
   Number(obj.valueOf());
}

上述代码,Number函数将obj对象转为数值,首先调用obj.valueOf方法, 结果返回对象本身;于是,继续调用obj.toString方法,这时返回字符串[object Object],对这个字符串使用Number函数,得到NaN

如果toString方法返回的仍不是原始类型的值,结果就会报错

js 复制代码
const obj = {
  valueOf() {
    return {}
  },
  toString() {
    return {}
  }
}
Number(obj);
// TypeError: Cannot convert object to primitive value

从上述可以看出,valueOftoString方法,是可以自定义的。

js 复制代码
// 验证会调用valueOf
const obj = {
  valueOf() {
    return 10;
  }
}
Number(obj); // 10

// 验证会调用toString
const obj2 = {
  toString() {
    return 20
  }
}
Number(obj2); // 20

// 验证valueOf方法先于toString方法
const obj3 = {
  valueOf() {
    return 10
  },
  toString() {
    return 20
  }
}
Number(obj3); // 10

数组为什么不一样?

js 复制代码
Number([5])    // 5
Number([1,2])  // NaN

原因拆解:

js 复制代码
[5].valueOf()  // [5]
[5].toString()   // "5"
Number("5")      // 5

[1,2].toString() // "1,2"
Number("1,2")    // NaN

执行顺序永远是:

valueOf方法 优先于 toString方法


2.2 String():转成字符串

(1)原始类型值

js 复制代码
String(123);        // "123"
String(true);       // "true"
String('test');     // "test"
String(undefined);  // "undefined"
String(null);       // "null"

对象规则

String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。

js 复制代码
String({a:1}) // "[object Object]"
String([1,2]) // "1,2"

String方法背后的转换规则,与Number方法基本相同,只是互换了valueOf方法和toString方法的执行顺序。

  1. 先调用自身toString方法,如果返回原始类型的值,则对该值使用String函数,不再进行后续操作。
  2. 如果toString方法返回的还是对象,则调用对象的valueOf方法,如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行后续操作。
  3. 如果valueOf方法返回的仍是对象,就报错。

例如:

js 复制代码
String({ name:'zhangsan' }); // "[object Object]"
// 等价于
String({ name:'zhangsan' }.toString()) // "[object Object]"

如果toStringvalueOf方法,返回的都是对象就报错。

js 复制代码
const obj = {
  toString() {
    console.log('1');
    return {}
  },

  valueOf() {
    console.log('2');
    return {}
  }
};

String(obj) // TypeError: Cannot convert object to primitxive value

从上述可以看出,toStringvalueOf方法,是可以自定义的。

js 复制代码
const obj = {
  toString() {
    console.log('1');
    // return {}
    return 10;
  },

  valueOf() {
    console.log('2');
    return 20;
  }
};
// toString方法如果返回10则输出'10'
// toString返回如果返回{},则继续执行valueOf方法,输出'20'
String(obj);

2.3 Boolean():最简单,但最容易踩坑

Boolean()函数可以将任意类型的值转为布尔值。它的转换规则比较简单,只有 5 个值是 false ,其他的值全部为true

js 复制代码
false
0
''
null
undefined
NaN
js 复制代码
Boolean({})   // true
Boolean([])   // true
Boolean(false) // false

⚠️ 所有对象的布尔值,永远是 true

4、隐式转换

(1) 自动转布尔(if 判断)

js 复制代码
if ('abc') {
  console.log('Hello');
}

等价于:

js 复制代码
if (Boolean('abc')) {}

快速写法:

js 复制代码
!!'abc' // true

(2)自动转字符串(+ 号)

js 复制代码
'5' + 1        // "51"
'5' + true     // "5true"
'5' + {}       // "5[object Object]"

核心规则:

只要有字符串,+ 就变成拼接


(3)自动转数字(- * /)

js 复制代码
'5' - '2'     // 3
'5' * []      // 0
'5' * [2]     // 10
'5' * [1,2]   // NaN

拆解 [] 的例子:

js 复制代码
[].toString()  // ""
Number("")     // 0

(4)一元运算符 +

js 复制代码
+'abc'   // NaN
+true    // 1
+false   // 0

JavaScript 的类型转换分为 显式转换隐式转换

  • 显式转换 :是开发者主动调用 NumberStringBoolean 等方法;
  • 隐式转换:发生在运算或条件判断中,由 JS 根据上下文自动完成;
  • 转换本质:根据运算符的预期类型,调用对应的转换规则。
相关推荐
QQ1__8115175155 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态5 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子5 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室5 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI5 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing5 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者5 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册5 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李5 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢6 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web