Js数据类型间的相互转换

前言:

我们在写js代码的时候,有些需求要用到数据类型的转换,或者也可能是我们无意间的操作让数据发生了类型转换,从而引起错误。熟悉Js数据类型间的相互转换规则至关重要,让我们来看看这其中的猫腻吧。

正文:

本文将介绍把其他类型数据转换成“Number”、“String”、“Boolean”的规则,以及“==”操作比较时的相互转换规则。

1.Number

Js中的数据类型转换有两种模式,一种是隐式转换,一种是显示转换
隐式转换:浏览器默认去转换,用Number()
情景1:数学运算

	console.log(10-'2');//8
	//等价于
	console.log(10-Number('2'));//8

情景2:isNaN检测

	console.log(isNaN('2'));//false
	//等价于
	console.log(isNaN(Number('2')));//false

情景3:==比较

	console.log('1'==1);//true

显示转换:自己手动用Number(),parseInt,parseFloat等

①Number

转换规则:
1.字符串转换为数字:空字符串变为0,如果出现任何非有效数字字符,结果都是NaN

    console.log(Number(''));//0
    console.log(Number('10'));//10
    console.log(Number('10px'));//NaN

2.布尔值转换为数字:true–>1,false–>0

    console.log(Number(true));//1
    console.log(Number(false));//0

3.null–>0,undefined–>NaN

    console.log(Number(null));//0
    console.log(Number(undefined));//NaN

4.Symbol无法转换为数字,会报错:Uncaught TypeError: Cannot convert a Symbol value to a number

	let a=Symbol('a')
	console.log(Number(a));//Uncaught TypeError: Cannot convert a Symbol value to a number

5.BigInt去除"n"

    console.log(Number(1n));//1

6.把对象转换为数字

  • 先调用对象的Symbol.toPrimitive 这个方法
  • 如果不存在这个方法,再调用valueOf获取原始值
  • 如果获取的值不是原始值,再调用对象的toString把其变为字符串
  • 最后再把字符串基于Number方法转换为数字
    举几个例子:

(1)Date()对象转Number

	let time = new Date();
	console.log(time);//Thu Aug 18 2022 15:23:47 GMT+0800 (中国标准时间)
    console.log(Number(time));//1660807427893

我们可以看到Number(time)输出的是毫秒数
在控制台中dir(time)
Js数据类型间的相互转换_第1张图片

可以看到有原型上有Symbol.toPrimitive ,属性值是一个方法

Js数据类型间的相互转换_第2张图片
按照规则,首先检测Symbol.toPrimitive,这里有,而且是个函数,就会执行!
我们可以试一下 time[Symbol.toPrimitive ](‘number’)
发现输出的也是毫秒数
在这里插入图片描述

(2)Number对象转Number

 	let num = new Number(10);
    console.log(Number(num)); //10

按照规则,首先检测Symbol.toPrimitive,发现Number没有,所以num[Symbol.toPrimitive]—>undefined

在这里插入图片描述

然后会调用valueOf,而这里num.valueOf()—>10,是原始值,转换完毕

在这里插入图片描述

(3)[]转Number

	let arr=[10]
	console.log(Number(arr)); //10

按照规则,首先我们来看看arr有没有Symbol.toPrimitive
在这里插入图片描述
arr[Symbol.toPrimitive]—>undefined,表示没有这个值
其次调用arr.valueOf(),这个方法肯定有,任何对象都有这个方法
Js数据类型间的相互转换_第3张图片
执行arr.valueOf()获取原始值—>[10],发现不是原始值,因为数组不是基本数据类型
然后调用toString
在这里插入图片描述
arr.toString()—>‘10’。最后再把字符串’10’转换成数字—>10,转换完毕

②parseInt与parseFloat

先看看与Number的区别:

    console.log(Number('12px')); //NaN
    console.log(Number(null)); //0
    
    console.log(parseInt('12px') ); //12
    console.log(parseInt(null)); //NaN

parseInt(val,radix)接受两个参数

  • 第一个参数val必须是字符串,如果不是,要先隐式转换为字符串,调用String()
  • 第二个参数radix表示进制,如果不写,或者写0,则默认是10进制
    (特殊情况:如果第一个参数是以0x开始的,则此时默认是16进制)
    有效范围:2~36之间
进制
2 0 1
3 0 1 2
8 0~7
10 0~9
16 0~9 A-F
36 0~9 A-Z

转换规则:从val字符串左侧第一个字符开始查找,查找出符合radix进制的值(遇到不符合的则结束查找,无论后面是否还有符合的),把找到的内容按照radix进制,转换为10进制!!!

举个例子:

console.log(parseInt('10102px13',2));//10

按2进制查找,找到1010,2不符合2进制,终止查找,查找结果是’1010’,再把这个二进制转换为10进制,最终结果就是10

再来看一道稍微复杂一点的题目:

    let arr = [27.2, 0, '0013', '14px', 123]
    arr = arr.map(parseInt)
    console.log(arr); //[27,NaN,1,1,27]

解析:
这里的map相当于

	arr.map((item,index)=>{
		return parseInt(item,index)
	})

展开就是下面这样

parseInt(27.2,0)
parseInt(0,1)
parseInt('0013',2)
parseInt('14px',3)
parseInt(123,4)

我们一个个分析:
parseInt(27.2,0):27.2按10进制找,找到小数点停止,得’27’用10进制转成10进制,最终结果是27
parseInt(0,1):1不在有效的进制范围,直接返回NaN
parseInt(‘0013’,2):0013按2进制找,得’001’,2进制001转成10进制,最终结果是1
parseInt(‘14px’,3):14px按3进制找,得’1’,3进制1转成10进制,最终结果是1
parseInt(123,4):123按4进制找,得’123’,4进制123转成10进制,最终结果是27
所以最终输出的是[27,NaN,1,1,27]

特殊情况:

    console.log(parseInt('0013',2)); //1
    console.log(parseInt(0013,2)); //3

原因:JS中以0开头的数字类型,会默认把其按照8进制转成10进制,然后再进行其他操作
所以parseInt(0013,2),首先把0013从8进制转成10进制,得11,然后再将11按2进制转成10进制,最终结果是3

parseFloat的转换规则比较简单,与parseInt的一样,只是没有进制的概念,都按10进制来

    console.log(parseFloat(10.1)); //10.1
    console.log(parseFloat('10.1')); //10.1
    console.log(parseFloat(null)); //NaN
    console.log(parseInt(10.1)); //10

2.String

情景1:String(val)或者val.toString()

转换规则:除对象以外,都是直接用字符串包起来

    console.log(String(1)); //'1'
    console.log(String(NaN)); //'NaN'
    console.log(String(null)); //'null'
    console.log(String(undefined)); //'undefined'
    console.log(String(Symbol())); //'Symbol()'
    console.log(String({})); //'[object Object]'

对象转字符串的转换规则,与对象转数字的规则一样:

  • 先调用对象的Symbol.toPrimitive 这个方法
  • 如果不存在这个方法,再调用valueOf获取原始值
  • 如果获取的值不是原始值,再调用对象的toString把其变为字符串

情景2:加号+

除了数学运算,还可能代表字符串拼接,也会发生字符串转换

(1)+有两边,一边是字符串或者某些对象

例1:

console.log(10+'10');	//'1010'

直接拼接

例2:

console.log(10+new Date());	//10Thu Aug 18 2022 17:25:52 GMT+0800 (中国标准时间)

按对象转字符串的转换规则
先new Date()[Symbol.toPrimitive] (‘default’)—>‘Wed Aug 03 2022 17:06:42 GMT+0800 (中国标准时间)’
得到字符串,然后拼接上10—>‘10Wed Aug 03 2022 17:06:42 GMT+0800 (中国标准时间)’

例3:

console.log(10+[10]);//'1010'

先[10] [Symbol.toPrimitive]—>undefined

然后[10].valueOf()—>[10]

再然后[10].toString()—>‘10’

最后10+'10’字符串拼接—>‘1010’

例4:一道面试题

let result=100+true+21.2+null+undefined+"ABC"+[]+null+9+false
console.log(result);	//NaNABCnull9false

这道题就留给读者分析吧
要注意undefined在运算中会变成NaN,任何数加NaN都等于NaN

(2)+值出现在左边

i是数字类型的时候

	let i=10;
	i++
	console.log(i);	//11

等价于

	let i=10;
	i=i+1;
	console.log(i);	//11

i是字符串类型的时候
连续++一定是数学运算!!!

	let i='10';
	i++
	console.log(i);	//11  连续++一定是数学运算

等价于

    let i = '10';
    i = i+1;
    console.log(i); //101	'10'+1->'101'

利用这个原理,我们有个编写Js代码的小技巧
加个+就能转成数字类型

    let num='10'
	console.log(+num);	//10
    console.log(typeof (+num));//number

数字加个空字符串也能转为字符串

    let str=10
	console.log(str+'');	//'10'
	console.log(typeof (str+''));//string

3.Boolean

转换规则:
除了“0/NaN/空字符串/null/undefined"五个值是false,其余值都是true
情景:

  • Boolean(val)
  • !/!! (!表示取反,!!表示取反再取反,所以!!跟Boolean()是一个意思)
  • 条件判断

这个比较简单就不举例了,记住就行

4.==比较时的相互转换规则

情景1:对象==字符串

按对象转字符串规则Symbol.toPrimitive—>valueOf—>toString
将对象转成字符串,然后比较

情景2:null==undefined
	console.log(null==undefined);//true
	console.log(null===undefined);//false

注意,null或undefined和本身比较是相等的,和其他任何值比较都不相等

	console.log(null==null);//true
	console.log(null===null);//true
	console.log(null=='null');//false

	console.log(undefined==undefined);//true
	console.log(undefined===undefined);//true
	console.log(undefined=='undefined');//false
情景3:对象==对象

比较的是堆内存地址,地址相同则相等

情景4:NaN
	console.log(NaN==NaN);//false
	console.log(NaN===NaN);//false

NaN与任何值都不相等,包括NaN本身

情景5:除了以上情景,只要两边类型不一致,剩下的都是转换数字,然后再进行比较

"==="绝对相等,如果两边类型不同,则直接是false,不会发生数据类型转换。
例1:

console.log([]==false);	//true

解析:都按前面提到的规则,转换为数字
第一步:[][Symbol.toPrimitive]—>undefined,没有Symbol.toPrimitive
在这里插入图片描述
第二步:[].valueOf()—>[],不是原始值
在这里插入图片描述
第三步:[].toString()—>‘’,得到空字符串,最后转换成0
在这里插入图片描述
第四步:按布尔值的转换规则,false—>0
第五步:0==0—>true

例2:

	console.log(![]==false);//true

先处理![],进行布尔类型转换,[]—>true,所以![]—>false
最后false==false—>true

以上就是Js数据类型间的相互转换的一些规则,感谢您的阅读,希望这篇文章能对你有所帮助,麻烦点赞收藏一下吧

你可能感兴趣的:(Js,javascript,前端,开发语言)