主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
主持人注意:请抵制编辑代码或删除此通知的冲动。空白模式可能是问题的一部分,因此不应进行不必要的篡改。如果您处于“空白是无关紧要的”阵营,您应该能够接受代码。
在JavaScript中,(a==1&&a==2&&a==3)是否有可能求值为真?
这是一家大型科技公司提出的面试问题。事情发生在两周前,但我仍在努力寻找答案。我知道我们在日常工作中从未编写过这样的代码,但我很好奇。
当前回答
这也可以使用一系列自重写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(“是的,这是可能的。”);}})();
其他回答
老实说,不管有没有一种方法可以评估它的真实性(正如其他人所展示的,有多种方法),我要寻找的答案是,作为一个已经进行了数百次面试的人来说,大致如下:
“嗯,也许是的,在一些奇怪的情况下,这些情况对我来说不是很明显……但如果我在真实的代码中遇到了这种情况,我会使用常见的调试技术来弄清楚它是如何以及为什么在做它正在做的事情,然后立即重构代码以避免这种情况……但更重要的是:我绝对不会在一开始就写代码,因为这就是复杂代码的定义,我努力不写复杂代码”。
我想有些面试官会对提出一个显然是非常棘手的问题感到愤怒,但我不介意有意见的开发人员,特别是当他们能够用合理的想法来支持这一点,并将我的问题融入到一个关于自己的有意义的陈述中时。
令人惊讶的是,是的。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)
我没有看到这个答案已经发布了,所以我也会把这个加入到混合中。这与Jeff使用半宽朝鲜文空格的回答类似。
变量a=1;变量a = 2.varа=3;如果(a==1&&a == 2 && а == 3) {console.log(“你好!”)}
你可能会注意到与第二个略有不同,但第一个和第三个与肉眼完全相同。所有3个字符都是不同的:
a-拉丁文小写aa - 全宽拉丁文小写Aа-西里尔文小写A
通用术语是“同字形”:看起来相同的不同unicode字符。通常很难找到三个完全无法区分的,但在某些情况下,你可能会很幸运。A、 Α、А和Ꭺ 会更好地工作(拉丁字母A、希腊字母Alpha、西里尔字母A和切罗基字母A);不幸的是,希腊语和切罗基语小写字母与拉丁字母A:α,ꭺ, 因此对上面的片段没有帮助)。
有一整类的同字形攻击,最常见的是假域名(例如,wikipediа.org(西里尔文)vs wikipedia.org(拉丁语)),但它也可以在代码中出现;通常被称为隐藏(正如一篇评论中所提到的,[隐藏]问题现在在PPCG上已不再是话题,但在过去,这类问题会成为一种挑战)。我使用这个网站来查找用于这个答案的同字形。
如果利用==的工作原理,您可以简单地创建一个带有自定义toString(或valueOf)函数的对象,该函数在每次使用时都会更改其返回的内容,以使其满足所有三个条件。
常量a={i: 1中,toString:函数(){返回a.i++;}}如果(a==1&&a==2&&a==3){console.log(“Hello World!”);}
这之所以有效,是因为使用了松散的相等运算符。使用松散相等时,如果其中一个操作数的类型与另一个不同,则引擎将尝试将其中一个转换为另一个。在左边是一个对象,右边是一个数字的情况下,它将尝试通过首先调用valueOf(如果它是可调用的)将对象转换为一个数字,否则,它将调用toString。在这种情况下,我习惯使用String,因为这是我想到的,valueOf更有意义。如果我从toString返回一个字符串,那么引擎将尝试将该字符串转换为一个数字,从而得到相同的最终结果,尽管路径稍长。
是的,您可以这样做,请参见以下JavaScript代码:
让a=0//创建一个变量并为其赋值如果(a!==1&&a!==2&&a!==3){console.log(“true”)}
解决方案说明:
简单地说,我们加上不等号在==符号之前,以便我们告诉语言这些值是不等于变量中的值