主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。

在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?

这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。


当前回答

相同,但不同,但仍然相同(可以多次“测试”):

常量a={valueOf:()=>this.n=(this.n||0)%3+1}如果(a==1&&a==2&&a==3){console.log(“Hello World!”);}如果(a==1&&a==2&&a==3){console.log(“Hello World!”);}

我的想法是从Number对象类型方程的工作原理开始的。

其他回答

通过在类声明中重写valueOf,可以执行以下操作:

class Thing {
    constructor() {
        this.value = 1;
    }

    valueOf() {
        return this.value++;
    }
}

const a = new Thing();

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

发生的情况是在每个比较运算符中调用valueOf。第一次,a等于1,第二次,a将等于2,依此类推,因为每次调用valueOf时,a的值都会递增。

因此,console.log将激发并输出(在我的终端中)Thing:{value:4},表示条件为真。

它可以在全局范围内使用以下方法完成。对于nodejs,在下面的代码中使用global而不是window。

var值=0;Object.defineProperty(窗口,“a”{获取:函数(){返回++val;}});如果(a==1&&a==2&&a==3){console.log(“是”);}

这个答案通过定义getter来检索变量,从而滥用了全局范围在执行上下文中提供的隐式变量。

如果利用==的工作原理,您可以简单地创建一个带有自定义toString(或valueOf)函数的对象,该函数在每次使用时都会更改其返回的内容,以使其满足所有三个条件。

常量a={i: 1中,toString:函数(){返回a.i++;}}如果(a==1&&a==2&&a==3){console.log(“Hello World!”);}


这之所以有效,是因为使用了松散的相等运算符。使用松散相等时,如果其中一个操作数的类型与另一个不同,则引擎将尝试将其中一个转换为另一个。在左边是一个对象,右边是一个数字的情况下,它将尝试通过首先调用valueOf(如果它是可调用的)将对象转换为一个数字,否则,它将调用toString。在这种情况下,我习惯使用String,因为这是我想到的,valueOf更有意义。如果我从toString返回一个字符串,那么引擎将尝试将该字符串转换为一个数字,从而得到相同的最终结果,尽管路径稍长。

这是可能的!

变量i=0;具有({获取a(){返回++i;}}) {如果(a==1&&a==2&&a==3)console.log(“wohoo”);}

这在with语句中使用getter,让一个求值为三个不同的值。

…这仍然不意味着这应该在实际代码中使用。。。

更糟糕的是,使用==也可以使用此技巧。

变量i=0;具有({获取a(){返回++i;}}) {如果(a!==a)console.log(“是的,这是打印的。”);}

我认为这是实现它的最小代码:

i=0,a={valueOf:()=>++i}如果(a==1&&a==2&&a==3){console.log('Mind===Blown');}

创建具有自定义值Of的虚拟对象,该值在每次调用时递增全局变量i。23个字符!