(a==1 && a ==2 && a==3)能否评估为真?

版主注:请抵制编辑代码或删除此通知的冲动。留白的模式可能是问题的一部分,因此不应该被不必要地篡改。如果你是在"whitespace is insignificant"阵营中,你应该能够接受代码的原样。

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

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

解决办法

如果你利用了==的工作原理,你可以简单地创建一个带有自定义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返回一个字符串,引擎就会尝试将字符串转换为数字,得到相同的最终结果,不过路径会稍长。

评论(19)

这是有可能的!

var i = 0;

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

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

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

更糟糕的是,这个技巧在使用===时也会起作用。

  var i = 0;

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

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

var val = 0;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

这个答案滥用了执行上下文中全局范围所提供的隐含变量,定义了一个getter来检索变量。

评论(6)