主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
当前回答
通过在类声明中重写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来检索变量,从而滥用了全局范围在执行上下文中提供的隐式变量。
我无法抗拒——其他答案毫无疑问是正确的,但你真的无法通过以下代码:
变量aᅠ = 1.变量a=2;变量ᅠa=3;如果(aᅠ==1&&a==2&&ᅠa==3){console.log(“你好!”)}
注意if语句中奇怪的空格(我从你的问题中复制的)。它是半宽朝鲜文(对于不熟悉的人来说是朝鲜语),它是一个Unicode空格字符,ECMA脚本不会将其解释为空格字符-这意味着它是标识符的有效字符。因此,有三个完全不同的变量,一个是a后面的朝鲜文,一个在a之前,最后一个只有a。为了可读性,将空格替换为_,相同的代码如下所示:
变量a_=1;变量a=2;var_a=3;如果(a_==1&&a==2&&_a==3){console.log(“你好!”)}
查看Mathias变量名验证器的验证。如果这个奇怪的间距真的包含在他们的问题中,我确信这是一个暗示,暗示了这种答案。
不要这样做。认真地
编辑:我注意到(虽然不允许启动变量)变量名称中也允许使用零宽度连接符和零宽度非连接符-请参阅用零宽度字符混淆JavaScript-利弊?。
如下所示:
变量a=1;变量a= 2; //一个零宽度字符变量a= 3; //两个零宽度字符(也可以使用另一个)如果(a==1&a==2&&a(&&a)==3) {console.log(“你好!”)}
正如我们已经知道的,松散相等运算符(==)的秘密将尝试将这两个值转换为公共类型。因此,将调用一些函数。
ToPrimitive(A)尝试将其对象参数转换为原语值,通过调用A.toString和A.valueOf的不同序列方法对A。
与其他使用Symbol.toPrimitive、.toString、.valueOf from integer的答案一样。我建议使用这样的array.pop数组。让a={array:[3,2,1],toString:()=>a.array.pop()};如果(a==1&&a==2&&a==3){console.log(“Hello World!”);}
通过这种方式,我们可以处理这样的文本
让a={array:[“World”,“Hello”],toString:()=>.array.pop()};如果(a==“你好”&&a==”世界“){console.log(“Hello World!”);}
这也可以使用一系列自重写getter:
(这类似于jontro的解决方案,但不需要计数器变量。)
(() => {“使用严格”;Object.defineProperty(this,“a”{“获取”:()=>{Object.defineProperty(this,“a”{“获取”:()=>{Object.defineProperty(this,“a”{“获取”:()=>{返回3;}});返回2;},可配置:真});返回1;},可配置:真});如果(a==1&&a==2&&a==3){document.body.append(“是的,这是可能的。”);}})();
这是可能的!
变量i=0;具有({获取a(){返回++i;}}) {如果(a==1&&a==2&&a==3)console.log(“wohoo”);}
这在with语句中使用getter,让一个求值为三个不同的值。
…这仍然不意味着这应该在实际代码中使用。。。
更糟糕的是,使用==也可以使用此技巧。
变量i=0;具有({获取a(){返回++i;}}) {如果(a!==a)console.log(“是的,这是打印的。”);}