如何让console.log( obj[0][1.5][10]==11.5)成立?

322 阅读2分钟

前言

有这么一个题目:

console.log( obj[0][1.5][10]==11.5) => true
console.log(obj[1][4] ==5); =>true
console.log(obj[1] ==5); =>false

如何让这个obj成立并且能判断是否相等?

解析

要想拿到这个obj中的[i],并且让这个i的值为取它的索引。我下面是用proxy实现

初步实现obj

const obj =(()=>{
     return "obj"
})()

上面实现使得每次使用console.log(obj)都会直接执行这个对象,这里用了立即执行函数(方法很多用自己习惯就行)

执行效果:

01.png

当每次使用索引拿值的时候都需要拿到索引值,可以封装一个方法 每次调用就行

const obj = (()=>{
   const proxyFn=(target ={})=>{
    console.log("target",target);
   }
   return proxyFn()
})()
console.log(obj); 

直接return 调用这个方法 ,使得每次自调用即可,方法里面返回一个proxy对象,要想索引值为索引 只需要修改get就能达到这个效果

const obj = (()=>{
   const proxyFn=(target ={})=>{
    return new Proxy(target,{
        get:(value,key)=>{
            console.log(value,key);
        }
    })
   }
   return proxyFn()
})()
console.log(obj[1]);
​

每次访问 obj[i]都会走这个get

执行效果:

02.png

下面只需要将其key复制为value返回出来即可,但是我们要对target(及传入的值做代理),并且传入多个索引时要将索引相加作判断

const obj = (()=>{
   const proxyFn=(target ={})=>{
    return new Proxy(target,{
        get:(value,key)=>{
            target.num =target.num || 0 
            target.num += Number(key)
            return proxyFn(target)
        }
    })
   }
   return proxyFn()
})()
console.log(obj[1][4]);

这里做了一层递归。给自己加了num作为初始化并累加时存储,再做代理

运行结果:

03.png

也达到了预期结果,传入的索引都能累加到num上,以上好像做完了,直接可以判断了 只需要拿num出来就行了。来试一下

运行结果: 04.png

运行显示报错 js引擎报错不能将类型进行转化并做运算?通过打印传入的key来看看此时都传入了什么?

05.png

通过打印可以看到 此时有一个symbol传入并且提示此symbol优先调用这个类型转化方法(Symbol.toPrimitive) ,了解原因后就好处理了,直接判断是否为symbol此类型然后给他赋值一次就完事了

运行结果: 06.png

判断后又出现新的问题,根据错误显示这个target.num被当作函数使用了?是什么原因呢?目前的理解就是第一次get返回了函数,后续的get都当做函数处理了(有懂的大佬可以指出),那么只需要将满足的返回一个函数即可

运行结果:

07.png

08.png

这样基本流程能跑通了,但是如果打印多个呢?会造成target.num进行累加(通过打印key就能发现),此时只需要将num重置即可

运行结果: 10.png

完整代码

const obj = (() => {
  const proxyFn = (target = {}) => {
    return new Proxy(target, {
      get: (value, key) => {
        if (key == Symbol.toPrimitive) {
          const num = target.num;
          target.num = 0;
          return () => num;
        }
        target.num = target.num || 0;
        target.num += Number(key);
        return proxyFn(target);
      },
    });
  };
  return proxyFn();
})();
console.log( obj[0][1.5][10]==11.5) 
console.log(obj[1][4] ==5)
console.log(obj[1] ==5)