分享一道有趣的题

本文最后更新于:2020年3月22日 晚上

今天在群里看到朋友发了一道有趣的题

就是如何让(a == 1 && a == 2 && a == 3) === true这个等式成立。一开始看到这个题觉得是无稽之谈,这不扯淡吗,一个变量能同时满足几个值?但是朋友这么问还真说不定有可能,于是开始一波思考。

首先分析一下等式左边的a==1a==2a==3,相等符号==会判断两个变量的值是否相等,如果不相等,则会触发变量类型的隐式转换;全等符号===则同时判断变量的值和类型,其中一个不相等,判断结果为false

然后我们假设等式已经成立,既然这个等式能够成立,那么变量a肯定不是一个普通的变量,至少基本数据类型满足不了这种骚操作,那么它应该是复杂数据类型

接着,对象跟基本数据类型做对比或运算的时候,会有我们上面说的类型隐式转换的一个过程,这里分三种情况:

  • 对象转换的规则,会先调用内置的 [ToPrimitive] 函数,如果部署了 Symbol.toPrimitive 方法,优先调用再返回;
  • 调用 valueOf(),如果转换为基础类型,则返回;
  • 调用 toString(),如果转换为基础类型,则返回;

如果上面几种情况都没有返回基础类型,就会报错。

那么分析到这里就很简单了,重写其中某个方法,覆盖默认行为:

触发隐式转换

我们分别给对象a重写覆盖了 Symbol.toPrimitivevalueOftoString方法,以方便我们调试。从控制台的输出可以看到,对象在判断转换过程中,会分别触发上述的方法,并且可以看到等式已经成立

这说明确实可以存在这种“不可思议”的情况。不过现实中不建议这样去改变对象的默认行为,往往会导致不可预料的后果。但是不可否认,这种骚操作的题,一定程度上可以反馈出我们对JS基础、底层操作的理解和积累。学习一途,真的是任重而道远啊~