小白学前端:一道数据类型转换题

119 阅读1分钟

题目

如何让下面的条件为真?

if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}

解决思路

首先,一个值要能 ==1 2 3,那么他绝对不可能是基本数据类型(number,string,boolean,null,undefined,symbol,bigint);

那么我们基本确定a是一个引用数据类型,笼统的说a是一个对象,再看 == 这个比较运算会在两边数据类型不同时,触发隐式的类型转换,那么问题就可以简化为:让a进行三次类型转换且分别转换为1 2 3;

对象转换成数字会触发三个隐藏副本( [Symbol.toPrimitive] / valueOf / toString ),这里我选取第一个,所以我们的第一个解决方案出炉了!

方案一:

let a = {
    arr:[1,2,3],
    [Symbol.toPrimitive]: function(hint){
        return this.arr.shift()
    }
}
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
}

除了借用类型转换,还有没有别的办法呢?当然有了。想一想,我们在 a == 1 这个语句执行时做了什么?第一步就是找到VO里变量a实际的值对吧?那么我们是不是可以借助一个叫数据劫持的东西做点文章?ok,那么第二个方案就出现了。

方案二:

+ 全局下声明的变量是window的一个属性

+ 用Object.defineProperty数据劫持(VUE2 也是靠这招实现的响应式数据)


let i = 0;

Object.defineProperty(window, 'a', {
    get() {
        return ++i;
    }
});

到此为止,我只想到了2种方式,也欢迎大佬补充