在我们日常的开发中总会用到大量的==、===、*、+、-等等符号,不过他们究竟是如何转换的,我们却不知道他的原理究竟是什么,接下来就带领大家探讨一下。
1、首先介绍一下大家所熟知的js的数据类型(原始数据类型和对象数据类型)
基础类型
number、bollean、string、null、undefined、symbol
复杂数据类型
object
2、 3种隐式类型转换
1、将值转为原始值,ToPrimitive()。
2、将值转为数字,ToNumber()。
3、将值转为字符串,ToString()。
隐式转换最关键的一点就是转换,什么是转换,如何转换,这就是个很重要的一点,比如在js中大家常常用到的的操作符号如+、==。
+可以是数字相加也可以是字符串相加、所以在转换的过程中就显得十分的麻烦,并且由于js中也存在==与===,这两种方式也有很大的不同。并且由于在js中也存在着-、*、/这几种运算符也就只能进行数字的运算,所以进行计算的参数究竟是如何运算转换的呢?
2.1、通过Toprimitive方法转换为原始值
在js中Toprimitive(input,preferedType?)的方法会有两个参数第一个未输入的值,第二个参数为想要转换的类型。
(1)如果类型为number时
1、如何输入的值是原始值,那么直接返回这个对象
2、如果输入值是一个对象的话,那么会调用这个对象的ValeOf()方法,如果是原始值则直接返回,否则的话调用tostring()这个方法,如果返回的的是原始值则直接返回,否则抛出异常TypeError。
(2)如果类型为String时
1、如何输入的值是原始值,那么直接返回这个对象
2、如果输入值是一个对象的话,那么会调用这个对象的tostring()方法,如果是原始值则直接返回,否则的话如果是个对象的时候,则调用对象的ValeOf()方法,如果是原始值则直接返回,否则抛出异常TypeError。
(3)如果没有类型参数时候
1、该对象为Date类型,则PreferredType被设置为String
2、否则,PreferredType被设置为Number
接下来解析一下valueOf方法和toString方法
在控制台输出Object.prototype,其中就有valueOf和toString方法,由于Object.prototype是所有对象原型链顶层原型,所有对象都会继承该原型的方法,所以对象都会有valueOf和toString方法。
valueOf究竟是如何转换的呢
1、Number、Boolean、String这三种构造函数生成的基础值的对象形式,通过valueOf转换后会变成相应的原始值。
如:var num = new Number(123)
num.valueOf() //123
2、Date为特殊格式,valueOf会转换为日期的毫秒形式
var a = new Date()
a.valueOf() // 1626674425216
3、其他的数据返回的都为this,即对象本身
var a = new Array()
a.valueOf() // []
ToString究竟是如何转换的呢
1、Number、Boolean、String、Array、Date、RegExp、Function这几种构造函数生成的对象,通过toString转换后会变成相应的字符串的形式,因为这些构造函数上封装了自己的toString方法。
var num = new Number('1asd');
num.toString(); // 'NaN'
var str = new String('12asd');
str.toString(); // '12asd'
var bool = new Boolean('fd');
bool.toString(); // 'true'
var arr = new Array(1,2);
arr.toString(); // '1,2'
var d = new Date();
d.toString(); // "Mon Jul 19 2021 14:04:00 GMT+0800 (中国标准时间)"
var func = function () {}
func.toString(); // "function () {}"
除这些对象及其实例化对象之外,其他对象返回的都是该对象的类型
var obj = new Object({});
obj.toString(); // "[object Object]"
Math.toString(); // "[object Math]"
2.2、ToNumber()将值转换为数字
参数 | 转换 |
数字 | 当前数字 |
undefined | NaN |
null | 0 |
布尔值 | true:1 false:0 |
字符串 | 位数字是是当前数字,否则NaN |
对象 | 先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToNumber转换为数字 |
2.3、通过ToString将值转换为字符串
参数 | 转换 |
数字 | 123 > '123' |
undefined | ’undefined‘ |
null | ’null‘ |
布尔值 | 'true' 或 'false' |
字符串 | 本身 |
对象 | 先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToString转换为字符串 |
例子:
1、2 * {} = ?
首先 *只能运算基础类型,并且为数字,所以2不需要转换,此时 {} 需要进行转换
1、会对 {} 采用ToPrimitive(input, Number)运算。
2、首先会执行valueOf方法,({}).valueOf(),返回的还是{}对象,不是原始值。
3、然后toString方法,({}).toString(),返回"[object Object]",是原始值。
4、"[object Object]"再进行ToNumber运算,"[object Object]"就转换为NaN。
所以结果就是2 * NaN = NaN
在工作中运用到最多的就是== 与===,但是这个究竟是什么原理呢?
== 运算符的规则并不是特别强,例如 :
x == y,会根据x、y的值返回true 或者false。
(1)若x和y的类型相同
1、 若 Type(x) 为 Undefined, 返回 true。
2、 若 Type(x) 为 Null, 返回 true。
3、若 Type(x) 为 Number, 则
(1)、若 x 为 NaN, 返回 false。(js规定NaN不等于本身)
(2)、若 y 为 NaN, 返回 false。
(3)、若 x 与 y 为相等数值, 返回 true。
(4)、若 x 为 +0 且 y 为 −0, 返回 true。
(5)、若 x 为 −0 且 y 为 +0, 返回 true。
(6)、返回 false。
4、若 Type(x) 为 String, 则当 x 和 y 为完全相同的字符序列(长度相等且相同字符在相同位置)时返回 true。 否则, 返回 false。
5、若 Type(x) 为 Boolean, 当 x 和 y 为同为 true 或者同为 false 时返回 true。 否则, 返回 false。
6、当 x 和 y 为引用同一对象时返回 true。否则,返回 false。
(2)若x和y的类型不相同
1、若 x 为 null 且 y 为 undefined, 返回 true。
2、若 x 为 undefined 且 y 为 null, 返回 true。
3、若 Type(x) 为 Number 且 Type(y) 为 String,返回比较 x == ToNumber(y) 的结果。
4、若 Type(x) 为 String 且 Type(y) 为 Number,返回比较 ToNumber(x) == y 的结果。
5、若 Type(x) 为 Boolean, 返回比较 ToNumber(x) == y 的结果。
6、若 Type(y) 为 Boolean, 返回比较 x == ToNumber(y) 的结果。
7、若 Type(x) 为 String 或 Number,且 Type(y) 为 Object,返回比较 x == ToPrimitive(y) 的结果。
8、若 Type(x) 为 Object 且 Type(y) 为 String 或 Number, 返回比较 ToPrimitive(x) == y 的结果。
9、返回 false。
例如 [] == !{} ???
此时会根据规则并且算数符的优先级进行转换
1、! 运算符优先级高于==,故先进行!运算。
2、!{}运算结果为false,结果变成 [] == false比较。
3、根据规则,等式右边y = false =ToNumber(false) = 0。结果变成 [] == 0。
4、按照规则,比较变成ToPrimitive([]) == 0。
按照上面规则进行原始值转换,[]会先调用valueOf函数,返回this。
不是原始值,继续调用toString方法,x = [].toString() = ‘’。
故结果为 ‘’ == 0比较。
5、根据规则,等式左边x = ‘’ =ToNumber(’’) = 0。
所以结果变为: 0 == 0,返回true,比较结束。