主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
当前回答
使用符号的ECMAScript 6答案:
const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));
由于==的用法,JavaScript应该强制a接近第二个操作数(本例中为1、2、3)。但是,在JavaScript尝试自己计算强制之前,它会尝试调用Symbol.toPrimitive。如果您提供Symbol.toPrimitive,JavaScript将使用函数返回的值。如果没有,JavaScript将调用valueOf。
其他回答
这是@Jeff的答案*的反转版本,其中使用隐藏字符(U+115F、U+1160或U+3164)创建类似于1、2和3的变量。
变量a=1;变量ᅠ1=a;变量ᅠ2=a;变量ᅠ3=a;console.log(a==ᅠ1和a==ᅠ2&&a(&&a)==ᅠ3 );
*这个答案可以通过使用零宽度非接合(U+200C)和零宽度接合(U+200D)来简化。这两个字符都允许在标识符内,但不能在开头:
变量a=1;变量a = 2.变量a = 3.console.log(a==1&a == 2&&a(&&a) == 3);/****变量a=1;var a\u200c=2;var a\u200d=3;console.log(a==1&&a\u200c==2&&a\u200d==3);****/
其他技巧也可以使用相同的思想,例如使用Unicode变体选择器创建看起来完全相同的变量(a︀ = 1.一︁ = 2.一︀ == 1和a︁ == 2; // 真)。
这是可能的!
变量i=0;具有({获取a(){返回++i;}}) {如果(a==1&&a==2&&a==3)console.log(“wohoo”);}
这在with语句中使用getter,让一个求值为三个不同的值。
…这仍然不意味着这应该在实际代码中使用。。。
更糟糕的是,使用==也可以使用此技巧。
变量i=0;具有({获取a(){返回++i;}}) {如果(a!==a)console.log(“是的,这是打印的。”);}
相同,但不同,但仍然相同(可以多次“测试”):
常量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对象类型方程的工作原理开始的。
这也可以使用一系列自重写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(“是的,这是可能的。”);}})();
面试规则一;永远不要说不可能。
不需要隐藏角色的诡计。
窗口__定义Getter__('a',函数(){if(类型i!=='number'){//在全局命名空间中定义i,以便在运行此函数后不会丢失i=0;}返回++i;});如果(a==1&&a==2&&a==3){console.log(“哦,亲爱的,我们做了什么?”);}