抛砖引玉
按照正常的逻辑来说,我们判断两个值是否相等会遵循以下规则:
但是我看下面一组值:
[]==0 //true []==false //true []==!{} //true [10]==10 //true '0'==false //true ''==0 //true undefined==null //true !null==true //true
居然没有按照我们的剧本走,那它比较规则又是什么?下面我就来分析一波。
“==”的比较规则
首先我们先去ECMAScript5.1中文版( http://lzw.me/pages/ecmascrip... )找一下“==”的比较规则,如下:
1.若Type(x)与Type(y)相同, 则
a.若Type(x)为Undefined, 返回true。
b.若Type(x)为Null, 返回true。
c.若Type(x)为Number, 则
i.若x为NaN, 返回false。
ii.若y为NaN, 返回false。
iii.若x与y为相等数值, 返回true。
iv.若x 为 +0 且 y为"text-align: center">
别看上面说的有点花里胡哨的,其实我们可以用很简单的话来总结出来。由于本篇文章核心是“==”是如何进行类型转换,我就总结一下类型不同的情况下“==”是如何比较的。
- 当数据类型为Boolean类型或者String类型时,比较时需要转换成Number类型。
- 当数据类型为引用类型时,需要转换成原始数据类型。当转换后的原始数据类型为Boolean类型或者String类型,则继续转换成Number类型。
- undefined和null跟任何值在“==”下都返回false,但二者在“==”下返回true。
具体流程图如下:
备注:
Javascript的数据类型可以分为以下两种:
- 原始数据类型(null、undefined、Number、String、Boolean、Symbol(Es6才引入的))
- 引用类型 (Object)
Boolean类型、String类型转换成Number类型的规则(ToNumber)
Boolean类型
Boolean Number true 1 false 0
String类型
标准的数字格式
如果是标准的数字格式,转换成Number类型相比不用多说,比如下面这几个栗子"htmlcode">"123" => 123 "12.34" => 12.34 "0.12" => 0.12 "-12.34" => -12.34非标准的数字格式
但是如果是非标准的数据格式,要分两种情况来考虑:
- 第一种:只包含数字并且最多只有1个点。
- 第二种:包含非数字以及含有多个1个点。
只包含数字并且最多只有1个点
这种情况下会首先进行补0和去0的操作,下面看几个栗子"htmlcode">
"01234" => 1234 ".1" => 0.1 "12." => 12 "1.000" => 1 "-02.30" => -2.3包含非数字以及含有多个1个点
这种情况下统统返回NaN,意为“Not a Number”,这里我们要注意一下,NaN还是Number类型,下面看几个栗子"htmlcode">
"123aa4" => NaN "哈喽,DD" => NaN typeof NaN => "numer"引用类型转换成原始数据类型的规则(ToPrimitive)
在介绍转换规则之前,首先我们我们介绍一下引用类型都带有的两个方法:
- Object.prototype.toString
- Object.prototype.valueOf
这二者都可以将引用类型转换成原始数据类型,接下来我们对二者做一个详细的介绍:
Object.prototype.toString
MDN是这样解释的:
The toString() method returns a string representing the object.(toString()这个方法返回一个代表这个对象的字符串)
举个栗子"htmlcode">
const obj = {} console.log(String(obj)) //"[object Object]" obj.toString = function(){ return 'Hello,Teacher Cang!' } console.log(String(obj)) //"Hello,Teacher Cang!"Object.prototype.valueOf
MDN是这样解释的:
The valueOf() method returns the primitive value of the specified object.( valueOf()这个方法返回这个对象的原始数据值)
举个栗子"htmlcode">
const obj = {} console.log(Number(obj)) //NaN obj.valueOf = function(){ return 12345; } console.log(Number(obj)) //12345valueOf和toString的优先级
关于这二者的优先级,在不同的情况下有着不同的优先级,下面我们根据不同情况介绍一下。
ToNumber
看个栗子"htmlcode">
const obj = { toString(){ console.log('调用了toString'); return 'Hello,Teacher Cang!'; }, valueOf(){ console.log('调用了valueOf'); return 12345; } } console.log(Number(obj)); 控制台输出结果: 调用了valueOf 12345通过上面的代码的运行结果,我们得出这么一个结论:
在ToNumber情况下,valueOf的优先级大于toString。
接下里我们看这么一种情况,如果valueOf返回的并不是原始数据类型会怎么样。
const obj = { toString(){ console.log('调用了toString'); return 12345; }, valueOf(){ console.log('调用了valueOf'); return {}; } } console.log(Number(obj)); 控制台输出结果: 调用了valueOf 调用了toString 12345从上面的运行结果中,我们可以得出这么一个结论:
在ToNumber情况下,如果valueOf返回的不是原始数据类型,则会自动调用toString。
打破砂锅问到底,再来一个非常极端的情况,如果说valueOf和toString返回的都不是原始数据类型,这时又该怎么样呢?同样,我们继续看一下运行结果:
const obj = { toString(){ console.log('调用了toString'); return {}; }, valueOf(){ console.log('调用了valueOf'); return {}; } } console.log(Number(obj)); 控制台输出结果: 调用了valueOf 调用了toString Uncaught TypeError: Cannot convert object to primitive value从上面的运行结果中,我们再次可以得出这么一个结论:
在ToNumber情况下,如果valueOf和toString返回的都不是原始数据类型,那么js会抛出异常,提示无法将引用类型转换原始数据类型。
根据三组代码的运行的结果,我们最后总结一下:
在ToNumber情况下,js会优先调用valueOf,如果valueOf返回的不是原始数据类型,则会接着调用toString,如果toString返回的也不是原始数据类型,js会抛出一个异常,提示无法将引用类型转换原始数据类型。
具体流程图如下:
ToString
看个栗子"htmlcode">
const obj = { toString(){ console.log('调用了toString'); return 'Hello,Teacher Cang!'; }, valueOf(){ console.log('调用了valueOf'); return 12345; } } console.log(String(obj)); 控制台输出结果: 调用了toString Hello,Teacher Cang!通过上面的代码的运行结果,我们得出这么一个结论:
在ToString情况下,toString的优先级大于valueOf。
同样我们看一下,toString返回的值不是原始数据类型时会怎样:
const obj = { toString(){ console.log('调用了toString'); return {}; }, valueOf(){ console.log('调用了valueOf'); return 'Hello,Teacher Cang!'; } } console.log(String(obj)); 控制台输出结果: 调用了toString 调用了valueOf Hello,Teacher Cang!根据运行结果我们可以得出:
在ToString情况下,如果toString返回的不是原始数据类型,则会自动调用valueOf。
最后我们看一下极端情况,二者返回的都不是原始数据类型:
const obj = { toString(){ console.log('调用了toString'); return {}; }, valueOf(){ console.log('调用了valueOf'); return {}; } } console.log(String(obj)); 控制台输出结果: 调用了toString 调用了valueOf Uncaught TypeError: Cannot convert object to primitive value我们又发现:
在ToString情况下,如果toString和valueOf返回的都不是原始数据类型,那么js会抛出异常,提示无法将引用类型转换原始数据类型。
我们将三个结论综合一下:
在ToString情况下,js会优先调用toString,如果toString返回的不是原始数据类型,则会接着调用valueOf,如果valueOf返回的也不是原始数据类型,js会抛出一个异常,提示无法将引用类型转换原始数据类型。
具体流程图如下:
“==”下的valueOf和toString的优先级
从文章前面我们总结出来“==”的比较流程来看,引用类型转换成原始数据类型之后,如果是Sting类型的话,还要再次转成Number类型,因此“==”下的引用类型转换原始数据类型过程中,遵循ToNumber的优先级规则。
const obj = { toString(){ console.log('调用了toString'); return 'Hello,Teacher Cang!'; }, valueOf(){ console.log('调用了valueOf'); return 12345; } } console.log(obj==12345); 控制台输出结果: 调用了valueOf trueconst obj = { toString(){ console.log('调用了toString'); return 12345; }, valueOf(){ console.log('调用了valueOf'); return {}; } } console.log(obj==12345); 控制台输出结果: 调用了valueOf 调用了toString trueconst obj = { toString(){ console.log('调用了toString'); return {}; }, valueOf(){ console.log('调用了valueOf'); return {}; } } console.log(obj==12345); 控制台输出结果: 调用了toString 调用了valueOf Uncaught TypeError: Cannot convert object to primitive value“==”之外的类型转换
“==”号只涉及到了ToPrimitive和ToNumber这两种转换,ToBoolean和ToString这两个没有涉及到的我们也介绍一下。
ToBoolean
对于ToBoolean,我们只需要记住几个特例是转成false的,其余的皆为true。
Boolean('') => false Boolean(undefined) => false Boolean(null) => false Boolean(0) => falseToString
Number to String
Number转String之前,首先会做一个去0和补0的操作,然后再去转成String类型。
String(1.234) => "1.234" String(NaN) => "NaN" String(.1234) => "0.1234" String(1.23400) => "1.234"Boolean to String
String(true) => "true" String(false) => "false"null和undefined to String
String(null) => "null" String(undefined) => "undefined"引用类型 to String
引用类型先ToPrimitive转换成原始数据类型,若转换后的原始数据类型不是String类型,再做String类型的转换。
const obj = { toString(){ console.log('调用了toString'); return true; } } console.log(String(obj)) 控制台输出结果: 调用了toString "true"总结
“==”下的类型转换,要分为两种情况来考虑。第一种,原始数据类型;第二种,引用类型。原始数据类型中String类型和Boolean类型是需要转换成Number类型再去比较的,而引用类型则需要先转换成原始数据类型再进行后续的转换。搞清整个流程之后,我们再去理解“==”涉及到的ToNumber和ToPrimitive是如何进行转换的。按照这样子的理解步骤走,我们对“==”隐藏下的类型转换会有比较清晰的认识。另外,“==”不涉及到ToString和ToBoolean的类型转换,在文章的后面部分我也加上去了,希望可以给小伙伴们一个更加全面的类型转换的认识。最后附上完整的“==”类型转换的流程图:
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]