“ 今天来讲解有趣的一篇文章,并且在面试中也会遇到,其实坑也是蛮多的,但是如果你真的理解了这篇文章,那么那些所谓的坑都是小意思,那么让我开始今天的分享吧。”
先来看一下转换类型是number数字类型会执行以下的步骤:
(1)如果是原始值(即一些代表原始数据类型的值,也叫基本数据类型),直接返回这个值;
(2)如果是对象,调用valueOf(),如果得到结果是原始值,返回结果;
(3)如果(2)不满足,则调用toString(),如果得到结果是原始值,返回结果;
(4)如果都不满足,抛出错误。
先来看一下转换类型是String数字类型会执行以下的步骤:
(1)如果是原始值(即一些代表原始数据类型的值,也叫基本数据类型),直接返回这个值;
(2)如果是对象,则调用toString(),如果得到结果是原始值,返回结果;
(3)如果(2)不满足,调用valueOf(),如果得到结果是原始值,返回结果;
(4)如果都不满足,抛出错误。
其实心细的你早已经发现了,转换类型是number或者string类型这两个的规则就是将(2)和(3)进行了一个翻转。
在实践之前,还需要记住的规则:只有当加法运算时,其中一方是字符串类型,就会把另一个也转化为字符串类型;而其他运算只要其中一方是数字,那么另一方就会转化为数字。
例一:
1 | // 例一 |
对于例一的解析步骤:
(1)由于上面说的规则,先看见数字1,此时右边的对象{}就会被转化成一个数字;
(2)再看到第一节中转化类型是number数字类型中对象被转换成一个数字,它首先会调用valueOf()方法,此时还是返回对象{},接着就会继续调用toString()方法,此时会被转化成’[object Object]’基本字符串类型;
(3)数字1再和字符串相加肯定就得到了上面我们所看到的结果’1[object Object]’。
例二:
1 | // 例二 |
虽然和例一中得到的结果是一致的,但是其解析过程是不一样的,对于例二的解析步骤:
(1)先看见字符串1,此时右边的对象{}就会被抓换成一个字符串;
(2)对象{}被转换成一个字符串,首先会调用toString()方法将其转化成’[object Object]’基本数字类型;
(3)最后字符串”1”再和”[object Object]”字符串进行拼接得到结果”1[object Object]”。
到这里是不是觉得其实对象转基本类型还是很简单的,只需要记住它的规则然后再仔细推敲就可以得出正确的结论。接下来难度还会再度升级,看看你还能正确的说出结果和解析过程吗?让我们继续吧!
难度升级***
例三:两边都是非数字或非字符串,记住一个原则:按照valueOf() —> toString顺序
1 | // 例三 |
对于例三的解析步骤:
(1)按照说的规则,左右两边的数组[]都会去转化为数字类型,也就是valueOf—>toString顺序来执行;
(2)数组[]转化为数字类型,首先会调用valueOf()方法,此时会返回数组[],由于还是对象类型,它会接着去调用toString()方法,然后返回一个空的字符串””;
(3)所以[]+[]就相当于””+””然后得到””空字符。
例四:
1 | // 例四 |
如果你对例三的解析很熟悉的话,那么例四对你来说就是小意思啦图片图片。对于例四的解析步骤:
(1)对于两边都是非数字或者非字符串,那么数组[]和对象{}都会被转换成数字类型;
(2)[]首先会去调用valueOf()方法转化为数组[],由于它是对象类型又会接着调用toString()方法,然后返回一个空的字符串””;
(3){}首先会去调用valueOf()方法转化为{},由于它是对象类型又会接着调用toString()方法,然后返回字符串”[object Object]”;
(4)””+”[object Object]”得到最终结果字符串”[object Object]”。
注意注意:下面练习难度再度升级,它会有坑欢迎大家来踩图片图片
难度再度升级*****
例五:
1 | // 例五 |
我猜你们是不是按照例四的解析过程来得到结论的,肯定有人会说这得到的结果不就和例四中的结果一样的吗?恭喜你成功踩到坑。
{}可以看成是对象,但是大家有没有想过它也可以是代码块呢。如果{}放到前面的话,浏览器会把它解析成代码块,代码块意味着它是什么用都没有的。这个时候后面的”+”并不是二元运算符号,而是一个一元运算符。这个时候数组[]变为数字类型,经过valueOf()和toString()方法之后变为空字符串,然后+””一元符将空字符串转化为数字0。
例六:
1 | // 例六 |
例六就是对例五的一个扩展,其实再外层添加括号才能得到我们最开始想要的结果值。这个时候在外层添加括号之后{}就不会被解析为代码块,会被解析为一个对象,至于过程还是对象{}和数组[]都会按照valueOf()和toString()的顺序来解析,最终得到”[object Object]”返回值。
例七:
1 | // 例七 |
首先需要声明:火狐浏览器解析出来时NaN,而Chrome谷歌浏览器解析出来时”[object Object][object Object]”,此时需要看你的浏览器怎么解析了。
在这里我按照火狐浏览器的解析结果进行一个讲解,例七解析步骤:
(1)第一个{}会被解析为代码块,然后将其忽略掉,然后加号会被解析为一元运算符,第二个{}对象会被解析为数字,首先执行valueOf()返回{}对象,然后调用toString()返回字符串”[object Object]”,由于+"[object Object]"
会被转化为数字,相当于隐私调用Number(“[object Object]”),最后给你返回NaN的值。
注意:如果我们期待第一个{}不是一个代码块而是一个对象时(如:{}+{}这种情况),可以考虑强制把输入解析成一个表达式来修复,是不是感觉有点拗口,别急,举个例子:
(1){}+{}转换成({}+{}),就这么简单;
(2)也可以考虑函数或方法的参数也会被解析成一个表达式,比如console.log({}+{}),它得到的结果也是”[object Object][object Object]”。
大晚上终于写完这篇文章了,爆肝了爆肝了,如果你觉得很赞的话喜欢能来个三连,也喜欢这篇文章能够帮助你对类型转换有了更好的理解。