如何让 a==1&&a==2&&a==3 成立?

430 阅读2分钟

如题,如何让 a==1&&a==2&&a==3 成立?

相信大家看到这样的问题就会很头疼,这该怎么实现呢?但是架不住某些面试官的高频提问,迫不得已寻找解决方案。

步入正题

一、利用 == 中的隐式类型转换

首先要清楚 == 运算符中都发生了什么

js调用==进行比较时,不同与===,双等号会触发类型转换,进行比较的事实上不是原始值,而是**toString()的返回值,所以我们可以从原型方法toString()**上做一点手脚:

let a = {
  toString(){
    return 'toString'
  }
}

if(a == 'toString'){
  console.log('toString 方法被重写')
}

可以看到可以重写,那现在只需要让 a 调用 toString() 方法的时候去返回一个自增的变量,可以这样做:

let a = {
  i:0,
  toString(){
    return ++this.i;
  }
}

if(a == 1 && a == 2 && a == 3){
  console.log('条件成立')
}

可以看到是没问题的:

但是这样还是远远不够的,面试官:还有其他的方法吗?

二、利用数据劫持 Object.defineProperty 来实现

我们都知道 Vue2.x 的双向数据绑定是利用 Object.definProperty 来实现的

利用同样思路,我们可以在条件判断获取 a 的时候去做数据劫持,返回一个自增的数字来实现:

let i = 0;
Object.defineProperty(window, 'a', {
  get(){
    return ++i;
  }
})
if(a == 1 && a == 2 && a == 3){
  console.log('条件成立')
}

可以看到条件还是成立的:

那有的人可能就有点疑问了,为什么要 return ++i 呢?不能直接 return ++a 吗?

我们来试一下:

可以看到浏览器给我们报了一个栈溢出的错误,原因是这样的

直接 return ++a 的话,浏览器肯定要先获取到 a 的值,再自增,获取 a 的值肯定会被 **Object.defineProperty 劫持到,**所以就造成了一个无限循环的递归,肯定会造成栈溢出。

三、还可以利用 toString() 方法

let a = [1, 2, 3];
a.toString = a.shift;

if (a == 1 && a == 2 && a == 3) {
  console.log('条件成立');
}

将数组 atoString() 方法重写,替换为 shift 方法,shift 方法是删除数组头部元素,并返回,这样的话每次调用 a 的 toString 方法就会删除第一个元素并返回

第一次做判断删除并返回 1

第二次删除并返回 2

....

以达成目的。

还有几种方法也都是通过数据劫持或者重写原型上的 toString 方法或 valueOf 方法,这里就不一一列举了。

如果你觉得这篇文章对你有帮助不妨评论留言分享,后续会有更多关于前端方面的知识和技巧。

转载自:lshblog.top/#/detail?id…