前言
有这么一个题目:
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)都会直接执行这个对象,这里用了立即执行函数(方法很多用自己习惯就行)
执行效果:
当每次使用索引拿值的时候都需要拿到索引值,可以封装一个方法 每次调用就行
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
执行效果:
下面只需要将其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作为初始化并累加时存储,再做代理
运行结果:
也达到了预期结果,传入的索引都能累加到num上,以上好像做完了,直接可以判断了 只需要拿num出来就行了。来试一下
运行结果:
运行显示报错 js引擎报错不能将类型进行转化并做运算?通过打印传入的key来看看此时都传入了什么?
通过打印可以看到 此时有一个symbol传入并且提示此symbol优先调用这个类型转化方法(Symbol.toPrimitive) ,了解原因后就好处理了,直接判断是否为symbol此类型然后给他赋值一次就完事了
运行结果:
判断后又出现新的问题,根据错误显示这个target.num被当作函数使用了?是什么原因呢?目前的理解就是第一次get返回了函数,后续的get都当做函数处理了(有懂的大佬可以指出),那么只需要将满足的返回一个函数即可
运行结果:
这样基本流程能跑通了,但是如果打印多个呢?会造成target.num进行累加(通过打印key就能发现),此时只需要将num重置即可
运行结果:
完整代码
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)