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

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

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


当前回答

好了,又一个发电机黑客:

常量值=函数*(){设i=0;而(真)产量++i;}();Object.defineProperty(this,“a”{获取(){return value.next().value;}});如果(a==1&&a==2&&a==3){console.log(“哟!”);}

其他回答

老实说,不管有没有一种方法可以评估它的真实性(正如其他人所展示的,有多种方法),我要寻找的答案是,作为一个已经进行了数百次面试的人来说,大致如下:

“嗯,也许是的,在一些奇怪的情况下,这些情况对我来说不是很明显……但如果我在真实的代码中遇到了这种情况,我会使用常见的调试技术来弄清楚它是如何以及为什么在做它正在做的事情,然后立即重构代码以避免这种情况……但更重要的是:我绝对不会在一开始就写代码,因为这就是复杂代码的定义,我努力不写复杂代码”。

我想有些面试官会对提出一个显然是非常棘手的问题感到愤怒,但我不介意有意见的开发人员,特别是当他们能够用合理的想法来支持这一点,并将我的问题融入到一个关于自己的有意义的陈述中时。

没有getters或valueOf的示例:

a=[1,2,3];a.join=a.shift;console.log(a==1&&a==2&&a==3);

这之所以有效,是因为==调用toString,它为数组调用.join。

另一种解决方案,使用Symbol.toPrimitive,它是ES6等价于String/valueOf:

设i=0;让a={[Symbol.toPrimitive]:()=>++i};console.log(a==1&&a==2&&a==3);

面试规则一;永远不要说不可能。

不需要隐藏角色的诡计。

窗口__定义Getter__('a',函数(){if(类型i!=='number'){//在全局命名空间中定义i,以便在运行此函数后不会丢失i=0;}返回++i;});如果(a==1&&a==2&&a==3){console.log(“哦,亲爱的,我们做了什么?”);}

令人惊讶的是,是的。JS中的==松散相等运算符调用被比较对象的valueOf()方法。因此,您可以创建一个类,该类返回一个内部值,然后在每次调用时递增该间隔值。这样地:

A类{构造函数(initalVal){this.val=初始值;}值Of(){返回此.val++;}}const a=新AClass(1);console.log(a==1&&a==2&&a==3)

我知道这个问题还有很多其他答案,但这就是ES6语法的用法。

注意:如果不希望发生这种情况,那么应该使用==运算符来检查strict。这样地:

A类{构造函数(initalVal){this.val=初始值;}值Of(){返回此.val++;}}const a=新AClass(1);console.log(a==1&&a==2&&a==3)

正如我们已经知道的,松散相等运算符(==)的秘密将尝试将这两个值转换为公共类型。因此,将调用一些函数。

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!”);}