JavaScript引用类型转换为原始类型(隐式类型转换问题)

首先,js中的类型转换有两种方式,一种是显式类型转换(强制转换),一种是隐式转换(隐式转换),强制转换一般为手动调用转换数据类型的API,如:Number()、String()、Boolean()...等等,而隐式类型转换一般发生在数据比较或者数据的运算中,一般是将运算符两侧的运算子转换为统一的数据类型进行比较,或者转换为两侧中一侧的数据类型(本质一样),而在转换中,基本数据类型的转换十分简单,如:字符串和数值进行比较、布尔值和数值进行比较,字符串和布尔值都会优先转换为数值,undefined和null比较结果为true、两边存在转换或者运算后为NAN的直接返回false...等等,这些都比较容易理解,而这次我们要讨论的则是,运算符两边存在引用数据类型的情况下,引用数据类型是如何进行转换为原始数据类型的,过程又是怎样?

1.在ES6之后提出了Symbol数据类型,同时内置了一个方法: Symbol.toPrimitive(),对于该方法的介绍是这样说的

  • 对象的Symbol.toPrimitive属性会指向一个方法,当前对象被转换为原始类型的值时,会调用这个方法,返回该对象对应的原始类型的值
  • 该方法默认接受一个字符串作为参数,表示当前的运算模式,运算模式有三种
    • Number: 该模式需要转换为数值
    • String: 该模式需要转换为字符串
    • Default: 该模式下既能转换为数值又能转换为字符串,属于默认模式

所以很明显,当一个引用类型需要转换为原始类型数据时,会率先调用该方法,那么让我们来使用一下,观察转换结果

        const object = {
            a: 1,
            [Symbol.toPrimitive]: () => {
                console.log("toPrimitive方法被调用了")
                return 1
            }
        }

        console.log(String(object))
        console.log(Number(object))
        console.log(Boolean(object))

结果:

显然除Boolean转换以外的string和number转换都成功返回了方法的返回值,(这里提一嘴,Boolean的转换,不会触发引用数据类型的转换,且Boolean转换中,除了undefined,null,NaN,0,为false之外否为true),OK,那么该对象在转换为原始类型数据之后就为1,那么,(object == 1)、(isNaN(object)、(object == “1”)、(object == true),这些的返回值都为true

这是转换的一种情况,方法返回的是一个基本类型数据,那么如果方法返回的依旧是一个引用数据类型呢? 转换结果会是怎样

        const object = {
            a: 1,
            [Symbol.toPrimitive]: () => {
                console.log("toPrimitive方法被调用了")
                return {}
            }
        }

        console.log(String(object))

很明显,报错了, 以上就是该方法的具体执行情况

那么如果在ES6之前又是如何进行引用数据转换为原始数据呢

2. 在Symbol.toPrimitive 方法出来之前,也有这一套转换规则,同样的引用数据类型中也会内置两个方法,一个是valueOf,一个tosSring,当需要被转换为数值时,就会调用valueOf,返回值就为转换后的原始数据类型,若需要转换为字符串类型时,就会调用,toString,返回值就为转换后的原始数据类型,具体代码分析如下

        const object = {
            a: 1,
            // [Symbol.toPrimitive]: () => {
            //     console.log("toPrimitive方法被调用了")
            //     return 1
            // }
            valueOf: () => {
                return 1
            },

            toString: () => {
                return "1"
            }

        }

        console.log(String(object) , typeof String(object))
        console.log(Number(object))

和 Symbol.toPrimitive方法相似,不过针对性更强,那么如果这两个方法返回值依旧为引用数据类型呢,会和Symbol.toPrimitive一样报错么,并不会,而是会继续去找另一种方法继续转换,如果继续转换返回值依旧是引用类型,则会报错,具体的情况如下图

 那么最后,结合上面ES6的Symbol.toPrimitive方法,引用数据类型转换为原始数据类型的过程就如下图:

以上就是转换的详细过程以及副作用,整体来说,这种转换有什么作用呢,或者说,在何种地方可以用,嗯... 恕我直言,这种的转换其实并没有什么具体的作用,总不能有人平白无故的将一个引用类型和基本类型的数据进行比较,那只能说他代码写错了,只能说这种转换在类型比较上增添了灵活性,说道代码写错了,那么这种转换就可以作为误差判断的一种标志,事先在引用类型数据上封装好转换函数的逻辑,当进行该转换的时候,说明出现了相关的引用类型和基本类型的比较,或者说进行了强制的类型转换一个引用数据类型到基本类型,那么就可以在转换函数逻辑中进行抛出错误,这样就可以形成错差判断的功能,除此之外我就想不到其他可以用到该种转换的场景了,虽然没什么用,但是理解其转换过程后,出现类似的抛错,我们也能快速的定位问题所在,也是一个十分重要的知识点呢。

相关图片资料引用来自:https://blog.csdn.net/TingYu168/article/details/105194212

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青灯夜游/

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值