当前位置: 首页 > 科技观察

面试官:(a==1&&a==2&&a==3)在JavaScript中可以为“真”吗?

时间:2023-03-19 14:34:49 科技观察

最近,我被问到一个非常有趣的面试问题:Can(a==1&&a==2&&a==3)everevaluatetotrueinJavaScript?。我几乎失去了我的工作机会,因为我无法回答。那一刻,我被这个问题吓了一跳,以为面试官在开玩笑。但当我看到他的“微笑”时,一种“你一定不知道答案”的感觉闪过脑海,这绝对不是一个容易解决的问题。文章将给出6个专业解答,让我们马上开始吧。方案一:valueOf&&toString第一种方案很简单,相信看完这段代码你会有思路。leta={name:'fatfish',toString(){return'medium'}}if(a=='medium'){console.log('hellomedium')}太神奇了,这是怎么回事?别担心,我的朋友,我会尽力解释原因。解释一些隐式转换规则当在JavaScript中使用==比较两个值时,它做了以下事情:将两个比较的值转换为相同的类型。变换后(可以变换方程的一侧或两侧),比较值。比较规则如下表所示:从表中可以得到一些信息。为了(a==1),a只能是以下内容:a是String类型,可转换为数字1('1'==1=>true)。a是布尔类型,可以转换为数字1(true==1=>true)。a是Object类型,可以通过“转换机制”转换为数字1。对象到原始类型的“转换机制”规则1和2没有什么特别的,我们来看规则3:当一个对象转换为原始类型时,会调用内置的[ToPrimitive]函数。逻辑大致如下:如果有Symbol.toPrimitive方法,先调用它。调用valueOf并返回是否可以转换为原始类型。调用toString,如果可以转换为原始类型则返回。如果没有返回原来的类型,就会报错。constobj={value:1,valueOf(){return2},toString(){return'3'},[Symbol.toPrimitive](){return4}}obj==4我的朋友,谢谢你耐心看了这么久,相信你心里已经有了答案。leta={i:1,valueOf(){returnthis.i++}}if(a==1&&a==2&&a==3){console.log('hellomedium')}方案二:数组&&隐式转换为串联数组对象也符合规则3,但在“toString”之前调用“join”方法。所以你可以从这里开始。leta=[1,2,3]a.join=a.shiftif(a==1&&a==2&&a==3){console.log('hellomedium')}解决方案3:使用"with"运营商MDN有一个关于with的使用的警告,就好像它的存在是一个错误。我从来没有在工作中使用过它,但它可以用来解决这个问题。leti=1with({geta(){returni++}}){if(a==1&&a==2&&a==3){console.log('hellomedium')}}你真聪明,我什至没有解释代码的含义。方案四:Symbol.toPrimitive我们可以使用隐式转换规则三来完成这道题(看完答案就知道为什么了!)。consta={i:1,[Symbol.toPrimitive](){returnthis.i++}}if(a==1&&a==2&&a==3){console.log('hellomedium')}数据劫持也是一条出路通过隐式转换,我们做了3个答案让a==1&&a==2&&a==3返回true,你一定想到了另一个答案,数据劫持,很棒的Vue我们用了为了赢得数百万开发者的芳心,我们也尝试用它来解决这个面试题。解决方案5:Object.defineProperty劫持'window'对象,并在每次读取'a'属性时将_a递增1。let_a=1Object.defineProperty(window,'a',{get(){return_a++}})if(a==1&&a==2&&a==3){console.log('hellomedium')}方案六:Proxy劫持数据还有一种方式,Vue3也用Proxy替换了Object.defineProperty。leta=newProxy({i:1},{get(target){return()=>target.i++}})if(a==1&&a==2&&a==3){console.log('你好媒体')}