大家好,我是R哥。
最近看到一个非常离谱的骚操作:一个对象,竟然能同时等于两个不同的值,比如你写 JS 代码 if (obj == 10 && obj == 100),它居然能满足两个条件并打印出结果。
第一次看到这个代码,我脑袋嗡嗡的,就两个字:离谱!
抱着好奇的精神研究了一番,当我搞懂背后的机制,才发现这其实是一种 巧妙利用语言特性的黑魔法,而且不仅在 JavaScript 中能玩出花来,Java 也能曲线救国整出个类似效果。
这篇文章就带大家从 JS 到 Java,掘地三尺把这个骚操作背后的本质讲清楚。
Javascript 版实现
如以下 Javascript 代码:
// 公众号:Java技术栈
var obj = {
i: 10,
valueOf: function() {
if (this.i === 10) {
this.i++;
return 10;
} else {
return 100;
}
}
}
if (obj == 10 && obj == 100){
console.log(obj);
}输出结果:
这里的 if (obj == 10 && obj == 100) 判断居然能同时满足?
其实这是利用了 valueOf 的可变返回值,第一次返回 10,第二次返回 100,所以 obj 可以做到同时等于两个不同的值!
这个对象 obj 有一个属性 i 和一个自定义的 valueOf 方法。
当你对一个对象进行如 obj == 10 这样的 非严格比较 时,JavaScript 会调用该对象的 valueOf() 方法(如果没找到,会再尝试 toString())。
第一次:obj == 10:
此时 obj.valueOf() 被调用:
if (this.i === 10) { // true
this.i++; // i 变成 11
return 10; // 返回 10
}于是 obj == 10 => 10 == 10 => ✅ 成立!
第二次:obj == 100:
再次触发 obj.valueOf():
if (this.i === 10) { // false,因为 i 已经是 11
...
} else {
return 100;
}返回 100,所以 obj == 100 => 100 == 100 => ✅ 成立!
我们还可以拓展一下更骚的写法:
let obj = {
i: 1,
valueOf() {
return this.i++;
}
};
if (obj == 1 && obj == 2 && obj == 3) {
console.log("骚操作成功!");
}输出结果:
骚操作成功!
Java 版实现
上面那个 JS 代码的核心是利用了对象的 valueOf() 方法在 == 比较中的自动调用,每次返回不同的值,从而实现了一个对象同时等于多个不同的值。
但在 Java 中并不能直接重载 == 的行为,因为 Java 中 == 比较的是 引用地址(对象)或基本类型的值,而不能像 JS 那样 “自动调用某个方法” 来参与比较。
不过,我们可以方法 + 状态变量实现类似的效果:
/**
* 公众号:Java技术栈
*/
public class Test {
private int i = 10;
public boolean equalsTo(int value) {
if (i == 10) {
i++; // i 从 10 -> 11
return value == 10;
} else {
return value == 100;
}
}
@Override
public String toString() {
return "MagicObject{i=" + i + "}";
}
/**
* 公众号:Java技术栈
*/
public static void main(String[] args) {
Test obj = new Test();
// 模拟 JS 的 a == 10 && a == 100
if (obj.equalsTo(10) && obj.equalsTo(100)) {
System.out.println(obj);
} else {
System.out.println("条件不满足");
}
}
}输出结果:
MagicObject
Java 版本也可以拓展一下更骚的写法:
/**
* 公众号:Java技术栈
*/
public class Test {
private int val = 1;
public boolean equalsTo(int input) {
return input == val++;
}
public static void main(String[] args) {
Test obj = new Test();
if (obj.equalsTo(1) && obj.equalsTo(2) && obj.equalsTo(3)) {
System.out.println("骚操作成功!");
}
}
}输出结果:
骚操作成功!
哈哈,虽然两种语言的实现原理不同,但思路一致,背后都是对 “状态变化 + 比较逻辑” 做了精心设计。
话说,这种代码有啥用?
说实话,你如果在真实项目中写出这种防御性骚代码,多半会被群起而攻之。但在面试、比赛、写博客、讲技术、装逼的时候,可能会是个绝活。
所以别只会看热闹,背后的机制才是我们真正要掌握的。
















