一、 问题提出
if (a == 1 && a == 2 && a == 3) {
console.log('Win')
}
今天逛论坛时发现了这样的一个面试题,让 a == 1&& a == 2 && a == 3 成立,说实在的,这……怎么可能嘛?亏这还是个面试题!怀着好奇心我接下去看了看才知道,原来还是我学识太浅了……
二、解决方式
解决方式我这里学会了两种:
第一种(toString)
const a = {
_a: 0,
toString: function() {
return ++a._a
}
}
运行一次,就给_a加1,然后返回.
因为toString是Object.prototype上面默认的方法,所以这个办法相当于把正常的隐式转换中toString 方法给拦截了。
涉及原型和原型链的知识点
问题是可以解决了。
评论区的有掘友说让 a = true 也可以解决的。确实很有误导性。其实是混淆了隐式转化的优先级。简单来说,隐式转化是由两部分组成:转化的规则 + 触发转化的条件。if包着的里面整体触发了Boolean()的转化规则,==又字符串在右侧触发toString()的转化规则。
回到这题,==的右边是数字,JS运行线路是从左到右的。所以,这个时候触发的是Number()的规则,把左侧的true转化为1之后,两边类型一致之后,那自然不会再触发什么规则了,此时已经不构成隐式转化。所以说1 == 1 && 1 == 2 && 1 == 3是不成立的。
现在记住了,也比面试过程中的时候再来记好
现在将题目简单修改一下,将双等变成三个等怎么办?
大家都知道===的话是先判断类型,再判断值。这里的toString已经默认把对象转化为字符串了.使用toStirng的话,结果就不成立了.
第二种(defineProperties)
使用对象的数据拦截法:
bash
Object.defineProperties(window, {
_a: {
value: 0,
writable: true
},
a: {
get: function() {
return ++_a
}
}
})
涉及到对象的访问器相关内容
链接:https://juejin.cn/post/7197782239685820475
来源:稀土掘金- 砂糖橘加盐