版主注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应不必要地篡改。如果您属于“空白无关紧要”的阵营,您应该能够接受代码原样。
是否有可能在 JavaScript 中(a== 1 && a ==2 && a==3)
评估为true
?
这是一家大型科技公司提出的面试问题。它发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从来没有写过这样的代码,但我很好奇。
版主注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应不必要地篡改。如果您属于“空白无关紧要”的阵营,您应该能够接受代码原样。
是否有可能在 JavaScript 中(a== 1 && a ==2 && a==3)
评估为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
,引擎就会尝试将该字符串转换为一个数字,从而得到相同的最终结果,尽管路径稍长。
我无法抗拒 - 其他答案无疑是正确的,但您真的无法跳过以下代码:
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!")
}
有可能的!
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.");
}
没有 getter 或 valueOf 的示例:
a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);
这是有效的,因为==
调用toString
它调用.join
数组。
另一种解决方案,使用Symbol.toPrimitive
ES6 等效于toString/valueOf
:
let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };
console.log(a == 1 && a == 2 && a == 3);
如果询问它是否可能(不是 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;
}
}
}