“让人头疼”的JavaScript数据类型隐式转换

本文详细探讨了JavaScript中的数据类型隐式转换,包括面试题解析、字面量、包装器与new方式的区别、数据类型转换规则,以及==比较运算符的工作原理。通过实例解析了加号+、减号-以及比较运算符><在不同类型数据间的操作。文章还总结了各类数据转换为布尔值的对照表,并提供了关键知识点的总结。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript数据类型隐式转换

1. 面试题

在讲JavaScript的数据类型隐式转换前,我们先看道面试题:

console.log(new String('abc') == true)

console.log({} == true)

console.log([] == ![])

结果是什么呢?

先把结果写下来,放在一边,然后继续看

2. 字面量形式、包装器方式,new 方式的区别

创建字符串的三种方式:

var a = 'Davie'                  //申明的是一个string类型,它是一个基本类型
var a = String('Davie')          // String()是一个包装类,用于将参数转换成string类型
var a = new String('Davie')     //采用new方式时创建了一个object类型

使用typeof验证上面的结论

var a='Davie'
console.log(typeof a) //string
console.log(typeof String(a)) //string
console.log(typeof(new String(a))) //object

3. JavaScript的数据类型

JavaScript的数据类型之前已经讲过了,忘记的朋友出门左转,查看搞懂JavaScript的数据类型

4. 各种类型隐式转换到布尔类型对照表

数据类型转换为true的值转换为false的值
Booleantruefalse
String任何非空字符串"" 空字符串
Number任何非零数字0和NaN
Object任何对象null
Undefined不适用undefined

5. !转换规则

!会将后面的数据先转成布尔值,然后取反。例如:

var a;
var r = !!a;
console.log(r) //false

!!{} // true
!!undefined // false
!!nul // false
!!NaN //fales

6. ==比较

比较操作符会为两个不同类型的操作数转换类型,然后进行严格比较。当两个操作数都是对象时,JavaScript会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。 ---- 引用自MDN

1. 类型相同的情况
  • 如果比较的是两个对象,则比较两个对象的指针是否指向同一个对象,例如:
var a = {}
var b = {}
a==b //false

很明显,ab在堆内存中是两个对象。二另一种情况:

var a = {}
var b = a;
a==b //true

这时,ab就指向了同一个对象,所以相等。

  • 其它的基本类型,如果是相同类型,则直接进行严格比较就好,没什么好说的。
2. 类型不同的情况

如果两边类型不同,则两边都尝试转成number类型。对于引用类型,先调用valueOf(),如果能转成数字,则进行比较。不能转成数字就调用toString()方法转成字符串。

var a = '123'
console.log(a == false)  //false,'123'转成数字是123,右侧转成数字是0,最终比较123==0
console.log(a==123)  //true,右边是数字,把左 边转成数字123

如果有一边是object类型:

var a = new String(123)
console.log(a==123) //true,a.valueOf()结果就是数字123,最终比较的是123==123

再看一个:

var a = {} 
console.log(a == 1)
//上面a==1在js解释引擎中的执行过程如下:
//a.valueOf()获取到的不是基本类型,调用a.toString()得到'[object Object]'
'[object Object]'==1;
//两边类型不致,左侧转成数字
NaN==1;//false,NaN跟任何类型比较都为false
3. null、NaN、undefined

null、NaN、undefined和string、number、boolean、object类型比较时,都不做隐式转换,比较的结果直接为false。但是需要注意以下几个规则:

console.log(NaN==NaN) //false
console.log(undefined==null) //true
console.log(null==null) //true
console.log(null==undefined) //true
undefined == undefined //true
4. 面试题解析

搞清楚规则后,开头的面试题就很容易了:

第一题:

//问题1:
console.log(new String('abc') == true)
 
//step1:右侧转成数字1,变成:
  new String('abc')==1
  //step2 new String('abc').valueOf()不是数字也不是字符串,再调用toString()
 '[object Object]' == 1
 //step3:字符串转数字
  NaN == 1 //false,NaN和任何类型比较都为false

第二题:

//问题2:
console.log({}==true)

//step1:右侧转成数字
{} == 1
//step2 {}.valueOf()不是数字也不是字符串,再调用toString()
'[object Object]' ==1  
//step3:字符串转数字
NaN == 1 //false,NaN和任何类型比较都为false

第三题:

//问题3:
console.log([]==![])

//step1:!优先级比==高,先转右边,[]是对象类型,转成布尔值为true,!true就是false
[]==false
//step2:右侧转成数字为0
[]==0
//step3:左侧是一个对象,valueOf()转出来不是字符也不是字符串,调用toString(),得到空字符串
'' == 0
//step4:字符串转成数字
0 == 0 //true
5. 总结
  • 类型相同
    • 基本类型,直接比较值
    • 引用类型比较指针
  • 类型不同,尝试转成number类型,
    • 先调用valueOf()转成number
    • 不行就再用toString()方法转成string
  • null、NaN、undefined单独一套规则

7. 比较运算符 > <

来,在来看一道题:

console.log('666' < '7')

正确答案是 true

这是因为字符串类型比较大小时,不进行类型转换,而是逐位比较ascii码,第1位不同则返回结果,否则继续比较第2位,直到某一位不同为止

在比如使用数组的sort方法排序:

var arr=[1,10,6,100].sort()

结果是:

[1, 10, 100, 6]

原因是sort()方法默认的比较规则会先把每个元素转成字符串,然后比较字符串的ASCII码来确定先后顺序。如果想要正确按照数字比较,则需要自定义比较函数:arr.sort((a,b) => {return a - b; });

8. 加号+

+运算符即可以对两个数相加,也可以连接字符串,那如果是[1,2,3]+4这种情况下又会发生什么呢?这就需要我们了解相应的规则,为了方便描述,我们把+号左侧的值叫做A,右侧的叫做B:
第一步:如果A和B都是number类型,直接相加;
第二步:接下来看A或B中是否有一个是否为string类型,如果有,则将另一个也转成字符串,然后连接;
第三步:既不是number,也不是string,则按如下规则转换:

  1. 能转换成数字,返回之

  2. 否则调用valueOf(),如果执行结果是基本类型,返回之;

  3. 否则调用toString(),如果执行结果是基础类型,返回之;

  4. 无法得到原始值,抛异常。

调用valueOf()返回的结果:

image-20210121174103788

调用toString()返回的结果:

image-20210121174141140

9. 减号-

除了加号外,减号也很神奇。

使用减号在做非数字类型的运算时,也会发生隐式类型转换。来看下面几个例子:

  1. true会转换成1
5 - true // 4 
  1. ''空字符串、null转成0
5 - '' //5
5 - null //5
  1. undefined和非空字符串转成NaN
5 - undefined // NaN
5 - 'a' // NaN
  1. 可以转成数字的字符串转成数字
5 - '1'  //4

End

如果这篇文章有所帮助,请点点赞,点点关注,谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值