实现JavaScript中的类型转换,理解显式类型转换和隐式类型转换

前言

在上一章讲了JavaScript中的数据类型以及类型判断的方法,接下来将来研究研究如何实现不同类型的相互转换,而类型转换主要含有两大部分:显式类型转换、隐式类型转换

原始值转原始值 ---显式类型转换

1. 转布尔 ---Boolean(x)

2. 转number ---Number(x)parseInt()parseFloat()

3. 转string字符串 ---String(x)以及.toString() 方法

原始类型转布尔的例子

js 复制代码
let s = 's'
let n = 123
let f = false
let u = undefined
let nu = null

console.log(Boolean(s));//true
console.log(Boolean(n));//true //只有0是false,其他都是true
console.log(Boolean(''));//false
console.log(Boolean(Infinity));//true无穷大
console.log(Boolean(f));//false
console.log(Boolean(u));//false
console.log(Boolean(nu));//false
console.log(Boolean());//false,什么都没有就默认为false 

其中要注意几点

  • 函数内为数字类型时,只有0会转换为false其余全转换为true
  • 函数内为Infinity(表无穷大)或者为无穷小时,当作数字类型处理
  • 为空时就默认输出为false

原始类型转number的例子

js 复制代码
console.log(Number('123'));//数字123
console.log(Number('123a'));//NaN不可描述的数字
console.log(Number(''));// 0
console.log(Number(true));//1
console.log(Number(false));//0
console.log(Number(null));//0
console.log(Number(undefined));//NaN
console.log(Number());//0
let intStr = "100";
let floatStr = "100.25";
let intNum = parseInt(intStr); // intNum 为 100
let floatNum = parseFloat(floatStr); // floatNum 为 100.25

要注意

  • undefined和复杂原始类型时输出NaN即不可描述的数字

原始类型转string字符串的例子

js 复制代码
console.log(String(123));//'123'
console.log(String(true));//'true'
console.log(String(false));//'false'
console.log(String(null));//'null'
console.log(String(undefined));//'undefined'
console.log(String());//''
console.log(String(Symbol()));//'Symbol()'
let bool = true; 
let strBool = bool.toString(); // bool 为 true,转换后 strBool 为 "true"

将对象转原始值 ---隐式类型转换

隐式类型转换是指在执行某些操作时,JavaScript引擎自动将一个数据类型转换为另一个数据类型,而无需程序员显式地调用转换函数。这种转换有时也被称为强制类型转换或类型协变。

1. 转布尔

  • 任何对象转布尔值,直接返回true

2. 转number

  • ToPrimitive: 这是JavaScript引擎内部的一个抽象操作,它负责将对象转换为原始值(字符串、数字、布尔值等)。此操作并不直接暴露为JavaScript的API,但在类型转换过程中起着核心作用。

在对象使用Number()函数转换时会有一下隐式的步骤

  • 先调用ToNumber(x),该函数中会再调用ToPrimitive()将对象转为原始值
  • ToPrimitive({obj},Number)
    1. 判断接收到的值是不是原始类型,是则返回该原始值,直接下班
    2. 如果不是原始类型,则调用obj.valueOf(),如果得到了原始值,则返回该原始值
    3. 否则调用obj.toString(),如果得到了原始值,则返回该原始值
    4. 则报错
js 复制代码
Number({})
1.ToNumber({})
2.let primValue = ToPrimitive({},Number)//[object,Object]
3.ToNumber("[object Object]")//NaN
4.得到结果:NaN


Number([])
1.ToNumber([])
2.let primValue = ToPrimitive([],Number)//''
3.ToNumber('')//0
4.得到结果:0

3. 转string字符串

在对象使用String()函数转换时会有一下隐式的步骤

  • 先调用ToString(x),该函数中会再调用ToPrimitive()将对象转为原始值
  • ToPrimitive({obj},String)
    1. 判断接收到的值是不是原始类型,是则返回该原始值,直接下班
    2. 否则调用obj.toString(),如果得到了原始值,则返回该原始值
    3. 如果不是原始类型,则调用obj.valueOf(),如果得到了原始值,则返回该原始值
    4. 则报错
js 复制代码
String({})
//隐式步骤
1.ToString({})
2.let primValue = ToPrimitive({},String)//"[object Object]"
3.ToString("[object Object]")//"[object Object]"
4.得到结果:"[object Object]"

注意这里和转number的区别,是先调用obj.toString()

隐式转换的其他情况

除了对象到原始类型转换这种情况,隐式类型转换还经常发生在以下场景中:

1. 算术运算:

一元操作符 +

几元就代表加号左右两边有几个元素

+号 会触发隐式类型转换,往number

js 复制代码
+[]
1.ToNumber([])
2.let primValue = ToPrimitive([],Number)//''
3.ToNumber('')
4.得到结果 0

+{}
1.ToNumber({})
2.let primValue = ToPrimitive({},Number)//"[object,Object]"
3.ToNumber("[object,Object]")
4.得到结果 Nan

二元运算符+

当参与运算的操作数不是同一类型时,某些值会被转换为数字。

  • 例如,'3' + 2 结果为 '32'(字符串连接)。只要左右两边有一个是字符串,结果都是字符串
  • '3' - 2 结果为 1(字符串 '3' 被转换为数字 3)。
js 复制代码
1 + '1' //'11'只要左右两边有一个是字符串,结果都是字符串

1 + [] // 1 + '' = '1' 存在字符串依旧按照字符串的拼接规则,而不转为数字 1 + 0

{} + [] // "[object,Object]" + '' = "[object,Object]"

2. 比较运算:

在比较操作中,不同类型的数据会被转换以进行比较。

  • true == 1 结果为 true,因为在比较前 true 被转换为 1
  • null == undefined 结果为 true,两者在比较时被视为相等。

== 与 ===的区别

  1. == 会触发隐式类型转换
  2. === 不会触发隐式类型转换,判断类型和值都相等,严格等于
js 复制代码
1 == '1' // true
//1 == Number('1') 触发隐式转换

1 === '1' // false
  • 使用==时会发生number类型的转换后在进行比较
  • 当使用===时代表的是严格等于,即不会发生任何形式的转换,直接进行比较,既要类型相同,值也要相同
js 复制代码
[] == ![] 
// !优先级更高
// [] == !ture
// [] == false
// [] == 0
// Number([]) == 0
// '' == 0
// 0 == 0
//得到true

这段代码展示了JavaScript中一个经典的类型转换和比较链,最终结果为true。下面是对这一过程的详细解析:

  1. !优先级更高 : 首先执行![],这里的!是一个逻辑非操作符,它会先于等号运算执行。对于一个非空数组[],它被当作真值处理,因此![]会得到false
  2. [] == false : 接下来比较[](空数组)和false。在进行==比较时,JavaScript会尝试将两边的操作数转换为相同类型再比较。
  3. [] == 0 : 因为直接比较数组和布尔值不是直观的比较,JavaScript会将两边都转换为数字类型进行比较。空数组[]转换为数字时,通过Number([])实现,这一步会先调用数组的toString()方法,得到空字符串'',然后将这个空字符串转换为数字0
  4. Number([]) == 0 : 正如上一步所述,空数组转换为数字0
  5. '' == 0 : 现在比较空字符串''和数字0。空字符串在进行数值比较时会被转换为0
  6. 0 == 0 : 经过一系列转换后,最终比较的是00,显然结果为true

3. 逻辑运算:

在逻辑运算中,如 if 语句或 &&|| 运算符,表达式会被转换为布尔值。

  • if ('text') 会执行代码块,因为非空字符串被视为 true

总结

类型转换主要含有两大部分:显式类型转换、隐式类型转换

显式类型转换较为简便,只需要注意一种场景:原始值转原始值

隐式类型转换则需要注意更多的场合,将对象转原始值,算术运算中的+,比较运算的=====,以及逻辑运算中的if 语句或 &&|| 运算符

相关推荐
过期的H2O215 分钟前
【H2O2|全栈】关于CSS(4)CSS基础(四)
前端·css
纳尼亚awsl29 分钟前
无限滚动组件封装(vue+vant)
前端·javascript·vue.js
八了个戒34 分钟前
【TypeScript入坑】TypeScript 的复杂类型「Interface 接口、class类、Enum枚举、Generics泛型、类型断言」
开发语言·前端·javascript·面试·typescript
西瓜本瓜@36 分钟前
React + React Image支持图像的各种转换,如圆形、模糊等效果吗?
前端·react.js·前端框架
黄毛火烧雪下37 分钟前
React 的 useEffect 钩子,执行一些异步操作来加载基本信息
前端·chrome·react.js
蓝莓味柯基42 分钟前
React——点击事件函数调用问题
前端·javascript·react.js
资深前端之路43 分钟前
react jsx
前端·react.js·前端框架
cc蒲公英1 小时前
vue2中使用vue-office库预览pdf /docx/excel文件
前端·vue.js
一嘴一个橘子1 小时前
js 将二进制文件流,下载为excel文件
javascript
Sam90291 小时前
【Webpack--013】SourceMap源码映射设置
前端·webpack·node.js