关于(a==1&&a==2&&a==3)=true问题的思考

作者 : 开心源码 本文共1441个字,预计阅读时间需要4分钟 发布时间: 2022-05-12 共228人阅读

这里考核的其实是非严格相等运算符==的原理,下面是摘自MDN的解释。

相等操作符比较两个值能否相等,在比较前将两个被比较的值转换为相同类型。在转换后(等式的一边或者两边都可能被转换),最终的比较方式等同于全等操作符 === 的比较方式。
相等操作符对于不同类型的值,进行的比较如下图所示:

image.png

在上面的表格中,ToNumber(A) 尝试在比较前将参数 A 转换为数字,这与 +A(单目运算符+)的效果相同。ToPrimitive(A)通过尝试调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)。

结合这道题,B的类型是Number,那么在A==B的比较中,可能存在两种情况的转换:

  1. 假如A类型是StringBoolean,则通过ToNumber()转换,它通过一元正号+(也等同于Number()函数)实现。这种实现是js语言内置的,无法重写。
  2. 假如A类型是Object,则通过toString()valueOf()方法实现。这两个方法是A的方法,是可以重写的。

所以思路就有了,首先确定A是一个对象,而后通过重写A的toString()valueOf()方法来达到目的。

所以代码是:

let a={  num:1,  toString(){    return a.num++  }}a==1&&a==2&&a==3 // true

或者者:

let a={  num:1,  valueOf(){    return a.num++  }}a==1&&a==2&&a==3 // true

延伸

略微修改上面的代码再来两个小测试,就能发现更多有意思的细节:

  • 在转换的时候,会先调用a.valueOf()方法,而后依照返回的值(假定叫res)做下一步的转换。
  • 假如res是Object的类型,则接下来调用a.toString()方法。
  • 否则,不再继续调用a.toString()方法,而是依据上表,对res做相应的转换,比方返回的是String或者者Boolean,则进行ToNumber(res)转换。

下面是测试代码:

// valueOf返回Object的情况let a={  num:1,  toString(){    console.log('toString')    return a.num++  },  valueOf(){    console.log('valueOf')    return {num:2}  }}a==1 // valueOf// toString// true
// valueOf返回Boolean的情况let a={  num:1,  toString(){    console.log('toString')    return a.num++  },  valueOf(){    console.log('valueOf')    return true  }}a==1// valueOf// true
// valueOf返回String的情况let a={  num:1,  toString(){    console.log('toString')    return a.num++  },  valueOf(){    console.log('valueOf')    return '1'  }}a==1// valueOf// true

参考链接:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
Advanced-Frontend/Daily-Interview-Question/issues/57

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 关于(a==1&&a==2&&a==3)=true问题的思考

发表回复