一文看懂JavaScript中的严格相等===、非严格相等、加法+等涉及的类型转换

大家好,我是小梅,公众号:「小梅的前端之路」 原创作者。

作为在前端领域不断探索的一员,在此记录开发中遇到的问题,如果你也遇到过相同的疑惑,希望本文对你有帮助。


写文背景:最近在看《你不知道的JavaScript(中卷)》,其中第一部分的第4章谈到了强制类型转换。作者写得很好,只是这知识它不入脑子啊,我看完就忘了作者讲了些啥,讲了太多的toNumber(),toString(),我全没记住!读完之后,脑袋里只剩下大大的疑惑,连x < y这种比较大小的都不会比较了。为了解决这个迷惑,打开了我下载回来还没怎么看过的ECMA-262.pdf,自我暗示,对着规范看,我肯定能理解了吧。

前提知识:toPrimitive()函数的作用,大家理解成它就是个把Object类型的数据转换成基本数据类型的函数就成,传入基本类型的数据就返回传入的参数本身。此处粘贴规范文档对它的解释。更多具体的转换步骤可以直接去看文档。不同版本的规范文档可能有一些些区别。

1、老生常谈的==和===

首先是非严格相等==,感兴趣的可以查看文档7.2.12 Abstract Equality Comparison章节。

非严格相等的x == y的比较如下:

1、x和y的类型相同,则参照严格相等来进行比较,见下文
2、如果x是null,y是undefined,则返回true; 如果x是undefined,y是null,则返回true
3、如果x、y双方有一个是Number类型,另外一个是String类型,则把String类型转换为Number类型再进行比较(不能转化为数字的将会转化为NaN,则会返回false)
4、如果x、y任意一个是Boolean类型,则将Boolean类型转换为Number类型再进行比较
5、如果x是Number、String、Symbol中的一种类型,而y是Object类型,则,调用toPrimitive(y)将y转换为基本数据类型再进行比较;反之同理。
其他情况,返回false

示例:

const a = {
  a1: 1
}
const b = a
const c = {
  a1: 1
}
console.log(null == null) // true
console.log(null == undefined) // true
console.log(12 == '12') // true
console.log('12a' == 12 ) // false
console.log(true == true) // true
console.log(a == b) // true, a,b变量所存的对象地址是一样的,因此是true
console.log(a == c) // false

严格相等的x === y的比较如下:

1、x和y的类型不相同,返回false
2、如果x、y都是Undefined或者Null类型的值,则返回true
3、如果x、y都是Number类型,按照Number类型比较,特殊的是x,y都是NaN,返回false;x,y一个为+0,一个为-0返回true,
4、如果是x、y是String类型的,则必须每个字母都相同才返回true,否则返回false
5、如果x、y都是true或者false则返回true
6、如果x、y都是Symbol、Object类型的值,如果他们的值一样(指引用的地址是同一个)则返回true, 否则返回false。

示例:

const a = {
  a1: 1
}
const b = a
const c = {
  a1: 1
}
console.log(12 === '12') // false
console.log(undefined === undefined) // true
console.log(+0 === -0) // true
console.log(NaN === NaN) // false
console.log('hello' === 'hello') // true
console.log(a === b) // true, a,b变量所存的对象地址是一样的,因此是true
console.log(a === c) // false

2、令人迷惑的x < y

感兴趣的可以查看文档7.2.11 Abstract Relational Comparison章节

x < y的比较步骤如下:

按照规范,首先调用toPrimitive(x, hint Number)如果x和y已经是基本类型,调用toPrimitive将直接返回本身
把x和y都转换成基本数据类型得到px和py,接下来就是比较px和py
1、如果px和py都是String类型的,则按照字符串的比较规则,如果px是py的前缀则返回false,如果字符串px,和py第k位的字母不相同,则比较第k位的两个字母的编码值,如果px='a222',py='b',字母a的编码小于字母b的编码值,因此px < py为true
2、如果px和py都是Number类型的,则正常的数字,相信大家都晓得咋比较
3、如果px是NaN,返回false; 如果py是NaN,返回false;(EMCAScript规范上写的是返回undefined,我在nodejs和浏览器环境中试了,都是返回false)
4、如果px是Infinity, 返回false;如果py是Infinity, 返回true
5、如果px是-Infinity, 返回true;如果py是-Infinity, 返回false
6、如果px是-0 and py是+0,返回false
7、如果px是+0 and py是-0,返回false

示例:

console.log('ac' < 'b') // true
console.log(1 < 2) // true
console.log(NaN < 2, NaN < NaN)  // false false
console.log(-Infinity < 2, Infinity < 2)  // true false
console.log(12 < -Infinity, 12 < Infinity)  // false true
console.log(-0 < +0, +0 < -0 )  // false false
console.log(12 < [123], 124 < [123])  // true false 数据转成字符串'123',再转成Number类型的数字123
console.log(12 < [], -1 < [], -1 < '')  // false true true 空数组转成字符串'',空字符串转成数字0
console.log(12 < [123, 'we'])  // false 数组转成字符串'123,we',该字符串转Number类型得到的结果是NaN
console.log('[a' < { a: 1 }, {}.toString())  // true [object Object] 对象转成字符串'[object Object]'

3、大家都会的 x + y

感兴趣的可以查看文档12.7.3 The Addition operator ( + )章节。

x + y的比较步骤如下:

首先调用toPrimitive()进行类型转换得到px, py
1、如果px、py有一个为String类型,则将另外一个转换为String类型,结果为拼接后的字符串
2、否则,就把两个都转为Number类型,直接进行算术上的加法。
3、不能转换成Number类型的,直接抛错,如:12 + Symbol(12)将会报错
在调用toPrimitive()的时候没有指定想要转换的类型,默认都是Number,只有日期类型的默认是String

示例:

console.log(12 + '13', typeof (12 + '13')) // 1213 string
console.log(12 + true, typeof (12 + true)) // 13 number ,true转换成Number类型的值是1, false是0
console.log(12 + null, typeof (12 + null)) // 12 number ,null转换成Number类型的值是1
console.log(12 + [], 13 + ['qww', '13'], typeof (12 + [])) // 12 13qww,13 string ,[]转换成String类型的值是''
console.log(12 + {}, typeof (12 + {})) // 12[object Object] string ,对象转换成String类型的值是'[object Object]'
console.log(12 + {a : 1}, typeof (12 + {})) // 12[object Object] string ,对象转换成String类型的值是'[object Object]'
console.log({} + 12) // [object Object]12 ,值得注意的是,当直接再控制台运行{} + 12返回的结果会是12,因为此时{}被看成是代码块而不是对象{}

更多有关toNumber、toString的细节都可以去文档中找答案,此处不再举例。

❤️欢迎素质三连[点赞 + 收藏 + 评论]

我是小梅,有兴趣的话可以在微信搜一搜「小梅的前端之路」第一时间接收文章更新通知,一起沟通、学习成长呀。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值