(a== 1 && a ==2 && a==3) 可以评估为真吗?

IT技术 javascript ecmascript-6
2021-01-15 16:28:25

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

是否有可能在 JavaScript 中(a== 1 && a ==2 && a==3)评估为true

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

6个回答

如果你趁如何==工作,你可以简单地创建一个自定义的对象toString(或valueOf改变它使用它,使得它满足所有这三个条件,每次返回)功能。

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}


这样做的原因是由于使用了松散相等运算符。使用松散相等时,如果一个操作数的类型与另一个不同,引擎将尝试将一个转换为另一个。在左边的对象和右边的数字的情况下,valueOf如果它是可调用的,它将尝试通过首先调用将对象转换为数字,如果失败,它将调用toString. toString在这种情况下使用它只是因为它是我想到的,valueOf会更有意义。如果我改为从 返回一个字符串toString,引擎就会尝试将该字符串转换为一个数字,从而得到相同的最终结果,尽管路径稍长。

根据一数量的转换将首先尝试了valueOf稍微好一点。
2021-03-13 16:28:25
评论不用于扩展讨论;此对话已移至聊天
2021-03-15 16:28:25
你能通过改变隐含的valueOf()操作来实现这一点吗?
2021-03-18 16:28:25
@Pureferret 等式比较的左侧是一个对象,而不是一个数字。该对象具有数字属性i并不会打扰引擎。;)
2021-04-08 16:28:25
是的,由于同样的原因,valueOf 代替 toString 起作用
2021-04-10 16:28:25

我无法抗拒 - 其他答案无疑是正确的,但您真的无法跳过以下代码:

var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

注意if语句中奇怪的间距(我从你的问题中复制的)。它是半角韩文(对于那些不熟悉的人来说是韩语),它是一个 Unicode 空格字符,ECMA 脚本不会将其解释为空格字符 - 这意味着它是标识符的有效字符。因此,存在三个完全不同的变量,一个在 a 之后是韩文,一个是在 a 之前,最后一个是 a。将空格替换_为可读性,相同的代码如下所示:

var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

查看Mathias 的变量名验证器上的验证如果他们的问题中确实包含了那个奇怪的间距,我相信这是对这种答案的暗示。

不要这样做。严重地。

编辑:我注意到(尽管不允许开始变量)零宽度连接零宽度非连接符字符也允许在变量名称中使用 - 请参阅使用零宽度字符混淆 JavaScript - 优缺点? .

这将如下所示:

var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
    console.log("Why hello there!")
}

@Baracus 是 RonJohn 在他对 Kevin 的回答的评论中注意到了奇怪的间距,这让我想起了这种(可怕的)技术,所以我不能因为发现它而受到赞扬。我有点惊讶没有人已经回答了这个问题,因为它在几年前因为某处的博客文章而在我的工作中出现 - 我现在有点认为这是非常普遍的知识。
2021-03-16 16:28:25
考虑到原来的间距,可能会更糟,即使用了一个变量var ᅠ2 = 3所以有三个变量aᅠᅠ= 1, ᅠ2 = 3, a = 3( a␣ = 1, ␣2 = 3, a = 3, so that (a␣==1 && a==␣2 && a==3))...
2021-03-20 16:28:25
当然,这是禁止作为标准漏洞,这也适用于面试。[需要引用]
2021-03-24 16:28:25
@AL-zami 在两个变量中有一个额外的字符,它在您的屏幕上显示为一个空格,但被解释为标识符的一部分,这意味着有三个单独的变量 - a、a 和 a - 额外的字符是韩文半宽空间。
2021-03-30 16:28:25
从原始问题中的奇数间距来看,我认为这正是面试问题正在寻找的答案 - 利用看起来像空格的非空格字符。好地方!
2021-04-10 16:28:25

有可能的!

var i = 0;

with({
  get a() {
    return ++i;
  }
}) {
  if (a == 1 && a == 2 && a == 3)
    console.log("wohoo");
}

这在with语句中使用 gettera评估三个不同的值。

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

更糟糕的是,这个技巧也适用于===.

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }

是的,我正在尝试同样的事情:) 所以面试中的正确答案是,“这不会发生在我的代码中,因为我从不使用with.”。
2021-03-14 16:28:25
@乔纳斯。很多人仍在使用,==但从那以后我就再也没有看到with过……实际上,JS 文档之外从来没有写过“请不要使用那个”。无论如何,一个很好的解决方案。
2021-03-15 16:28:25
@Pointy在接受的答案,他们这样做没有类似的东西with,因此它可以发生
2021-03-17 16:28:25
@jorrit 没有人会使用==. ===阻止接受的答案
2021-03-27 16:28:25
@Pointy - 而且,我在with不允许的严格模式下编程
2021-03-28 16:28:25

没有 getter 或 valueOf 的示例:

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

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

另一种解决方案,使用Symbol.toPrimitiveES6 等效于toString/valueOf

let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };

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

这很有意义,几乎感觉很有用。
2021-03-18 16:28:25
老实说,我认为这是最好的答案。它不涉及任何异常,只是设置一些值。即使有基本的 JS 知识也很容易理解。做得好。
2021-03-19 16:28:25
我知道大多数答案都是关于滥用的toStringvalueOf但这个答案让我完全措手不及。非常聪明,我不知道它确实在.join内部调用,但它完全有道理。
2021-03-24 16:28:25
without valueOf,嗯……它更间接,但基本上是一样的。
2021-03-26 16:28:25
我真的很喜欢这个解决方案,因为除了对象自己的连接函数之外,你不会覆盖任何东西,而且它只是一个非常干净且易于阅读的 hack,它使逻辑评估为真。
2021-03-27 16:28:25

如果询问它是否可能(不是 MUST),它可以要求“a”返回一个随机数。如果它依次生成 1、2 和 3,则为真。

with({
  get a() {
    return Math.floor(Math.random()*4);
  }
}){
  for(var i=0;i<1000;i++){
    if (a == 1 && a == 2 && a == 3){
      console.log("after " + (i+1) + " trials, it becomes true finally!!!");
      break;
    }
  }
}

最低:1,最高:412。
2021-03-19 16:28:25
我喜欢这个答案,因为它考虑到了极点表明,这是可能的任何语言,如果该程序运行时CPU的寄存器/缓存中被击中有足够的宇宙射线,或者如果硬要把执行电源故障,使得故障分支if 条件实际上并没有跳转。
2021-03-28 16:28:25
即使我知道其他解决方案,我也会故意给出这个答案,因为它回答了问题,但显然不是他们所追求的。玩愚蠢的游戏,赢得愚蠢的奖品。
2021-04-05 16:28:25
但是如果需要超过 1000 次试验呢?
2021-04-05 16:28:25
@Piyin 如果需要超过 1000 次试验,您将获得奖品!
2021-04-09 16:28:25