JavaScript的“变脸”艺术:类型转换戏法大揭秘

引言

如果要评选 JavaScript 中最让人抓狂的特性,隐式类型转换绝对榜上有名。你一定经历过这样的绝望时刻:明明看起来是 true,条件判断却走进了 false 的分支;明明是在做加法,结果却得到了字符串拼接。更别提那个堪称前端面试"经典刑具"的灵魂拷问:\[\] == !\[\] 为什么是 true?在无数次与 == 和 + 斗智斗勇后,我们往往只能无奈地默念"万能的 === 保平安"。但逃避并不能解决问题,今天,就让我们不再依赖玄学,彻底扒开 JavaScript 类型转换的底裤,看看这些离谱操作背后,究竟藏着怎样的运作逻辑。

类型转换

在讲类型转换之前我们先来看看 == 和 === 有啥区别。

== :在判断相等的过程中会发生隐式类型转换

显示类型转换:

  • String(x) --> ToString(x)
  • Number(x) --> ToNumber(x)
  • Boolean(x) --> ToBoolean(x)

在写代码的时候我们会进行一些类型转换,如将转换成 String 类型

javascript 复制代码
console.log(String());  // ''

console.log(String(undefined));   // 'undefind'

console.log(String(null));  // 'null'

console.log(String(true));  // 'true'
console.log(String(false));  // 'false'

console.log(String(0));  // '0'
console.log(String(NaN));  // 'NaN'
console.log(String(Infinity));  // 'Infinity'

然后我们来看一下输出结果:

那为什么会输出这些呢?在转换成 String 的类型时其实是调用了 ToString 这个官方定义的方法。所以我们直接去看一下官方文档里面的 ToString 里面的内容。

其中的 Object 转换我们等会再讲,我们继续来看转换成 Number

javascript 复制代码
console.log(Number());   //  0
console.log(Number(undefined));   //  NaN
console.log(Number(null));   //  0
console.log(Number(true));   // 1
console.log(Number(false));   // 0
console.log(Number('123'));   // 123
console.log(Number('-123'));   // -123
console.log(Number('000123'));   // 123
console.log(Number('000123a'));   // NaN

依旧看一下输出结果:

ok,输出这些还是官方定义的 ToNumber 提前定义好的,我们依旧可以去官方文档上寻找答案。

最后一个我们要转换成 Boolean 类型呢?看完上面的你应该已经知道怎么说了吧,肯定是调用 ToBoolean ,没错,就是调用 ToBoolean

我们还是看一下官方文档中的 ToBoolean:

引用类型转字符串

说到引用类型转字符串,前面我们不是跳过了吗?其实是因为它有点特殊。我们就用引用类型转字符串来先看看有什么特殊。

javascript 复制代码
console.log(String({a:1}));
console.log(String([]));

我们先来看看这两个输出结果:

对象的输出结果是 object Object 数组的输出结果为 '' 。那为什么输出结果是这两个呢?其实是因为转换的过程中调用了ToPrimitive 这个方法。

完整的过程:

String(x) --> ToString(x) --> ToPrimitive(x,String)

而其中的 ToPrimitive 依旧是官方定义的,我们还是先看一下官方文档

而其中的引用类型有要去查看 8.12.8

那我直接用我们看的懂的方式来说明白这些,其实就是下面的这些步骤:

ToPrimitive({a:1},String)

css 复制代码
 1. 调用 {a:1}.toString(),如果得到一个原始值,则返回
 2. 调用 {a:1}.valueOf(),如果得到一个原始值,则返回
 3. 否则,报错

中间我们又需要调用到 toStringvalueOf 方法,我们来补充一下这两种我们能使用的方法吧。

toString 和 valueOf

toString:

  1. {}.toString() --> 返回 "object Object"
  2. \[\].toString() --> 返回 '' 返回数组内部的元素以逗号分隔的字符串
  3. xx.toString() --> 返回 "xx" 返回xx的字符串形式

valueOf:

valueOf() 只能将包装类的对象转换成原始值

现在我们应该知道怎么引用类型转字符串了,我们接着来聊引用类型转数字

引用类型转数字
javascript 复制代码
console.log(Number({})); 
console.log(Number([]));

我们还是先看输出结果:

其实引用类型转数字的步骤是和转字符串差不多的依旧是:

Number(x) --> ToNumber(x) --> ToPrimitive(x,Number)

但是其中的 ToPrimitive 有点区别,我们就来看看 ToPrimitive(x,Number) 的过程吧

ToPrimitive({a:1},Number)

css 复制代码
 1. 调用 {a:1}.valueOf(),如果得到一个原始值,则返回 
 2. 调用 {a:1}.toString(),如果得到一个原始值,则返回
 3. 否则,报错

其实就是把第一步和第二步换了一下顺序。

引用类型转布尔类型

这个我们只需要记住一句话:所有的引用类型转 布尔 都是 true

隐式类型转换

说到隐式类型转换其实我们只需要它是什么时候进行的进行了。

隐式类型转换几种法式:

  • 四则运算: + - * / %
  • 判断语句: if while == >= <= != > <

说到 + 这个有点特殊需要我们注意一下。

+作为一元运算符 (朝 number 转换)

+作为二元运算符 (朝字符串转换)

scss 复制代码
 x + y
 令 lprim 为 ToPrimitive(x) 的结果
 令 rprim 为 ToPrimitive(y) 的结果
 lprim + rprim
 如果 lprim 或者 rprim 有一个是字符串,就将另一个也转成字符串进行拼接
 否则全部转 number 进行相加

总结

JavaScript中==运算符、四则运算及判断语句会触发隐式类型转换,其中引用类型转换需遵循ToPrimitive规则:转字符串优先调用toString()再调用valueOf(),转数字则相反,且引用类型转布尔值恒为true;显式转换主要通过String、Number、Boolean函数进行,特别值得注意的是二元运算符+在拼接字符串时会将非字符串侧转为字符串,否则转为数字相加。

相关推荐
前端Hardy1 小时前
21.8 万周下载!这个 React 表格组件,10 行代码就能跑起来
前端·javascript·后端
陈_杨1 小时前
鸿蒙APP开发-带你走进胶片录的拍摄记录管理
前端·javascript
陈_杨1 小时前
鸿蒙APP开发-带你走进胶片录的相机控制
前端·javascript
陈_杨1 小时前
鸿蒙APP开发-带你走进节流战的Canvas图表
前端·javascript
陈_杨1 小时前
鸿蒙APP开发-带你走进光绘记的拍摄规划
前端·javascript
陈_杨1 小时前
鸿蒙APP开发-带你走进光绘记的长曝光模拟
前端·javascript
陈_杨1 小时前
鸿蒙APP开发-带你走进节拍器的声音怎么这么准
前端·javascript
riuphan3 小时前
揭秘 JS 类型转换:ToPrimitive 机制的神秘面纱
前端·javascript
sagima_sdu4 小时前
Vue 前端径向渐变背景制作
前端·javascript·vue.js