奇怪的问题 a==1 && a==2 && a==3

a == 1 && a == 2 && a == 3

题目很简单,只要让if语句中的判断条件成立即可。

if (a == 1 && a == 2 && a == 3) {
	console.log('win!!!');
}

首先分析题目,题目的意思只要我们能够让a同时与1,2,3相等的话,那么此时就成功了。很显然此时a并不能只是一个普通的值,因为如果a只是一个普通值的话,它是没有办法做到同时与三个值相同的。这条思路行不通,我们需要再想想其它的方法。
其实我们可以从==运算符下手,提到 == 我们可以联想到隐式类型转换,那么我们可不可以通过隐式类型转换来处理这道题呢,分析一下。
既然牵扯到隐式类型转换,无非就存在下面几种转换的规则:

  1. toPrimitive()Symbol.toPrimitive => valueOf => toString

将值转为原始值(原始类型)

  1. toNumber()Symbol.toPrimitive => valueOf => toString

将值转为数字

  1. toString()Symbol.toPrimitive => toString => valueOf

将值转为字符串
熟悉完规则后,我们再来看看题目。虽然a不能是原始值,但是我们可以将a设置为一个对象的形式,当对象与数值进行==运算的时候,是会执行toPrimitive规则的隐式转换逻辑。

var a = {
	step: 0,
	toString() {
		return ++this.step; 
	}
}
if (a == 1 && a == 2 && a == 3) {
	console.log('win');
}

a === 1 && a === 2 && a === 3

那么如果替换稍微变换的话,那么我们又该如何操作呢?刚刚是==运算符,是存在隐式转换的问题。而如果此时是===严格相等的话,那么就不存在隐式转换的问题。那么我们又该如何设计呢?
既然现在的情况是不存在隐式转换的问题,那么我们就没有办法通过valueof/toString方法去解决这个问题了,因为此时是不会调用toString、valueof方法。
我们再次分析if(a === 1 && a === 2 && a === 3)题目,当在执行a === 1的时候,程序是要去访问a的值,这样才能够进行对比。既然存在访问a这个操作,那么我们是不是可以通过数据劫持的方式来对a值进行处理呢?

if (a === 1 && a === 2 && a === 3) {
	console.log('win!!!');
}

如果用到数据劫持的话,我们可以使用Object.defineProperty()方法来处理。但是defineProperty是需要在对象上定义属性,而我们的a属性放在哪里比较合适呢?当然是存放在window对象上比较合适。所以我们可以这样去做:

var step = 0;
Object.defineProperty(window, 'a', {
	get () {
		return ++step;
	}
});
if (a === 1 && a === 2 && a === 3) {
	console.log('win!!!');
}

再次改变一下题目,如果题目换为下面的方式,又该如何操作呢?

if (obj.a === 1 && obj.a === 2 && obj.a === 3) {
	console.log('win!!!');
}

很简单,也是数据劫持。但是我们可以不用defineProperty对象定义属性的方式去做,我们可以直接在对象中通过语法糖的方式进行处理。比如说像下面一样去做:
get、set函数是直接可以写在对象内部中去。

var obj = {
	_step: 0,
	get a() {
		return ++ this._step;
	}
}

if (obj.a === 1 && obj.a === 2 && obj.a === 3) {
	console.log('win!!!');
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️不倒翁

你的鼓励就是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值