浅谈Map.get与Map.has以及内部原理

Map.has和Map.get性能?

经常使用Map总是会在想要不要用has?看题解总是能看到,但自己个人感觉不是必要的,因此探讨一下:
文档: ECAMScript

Map.prototype.get ( key )
Map.prototype.has( key )
在这里插入图片描述
上图来自文档中

这里大致讲解一下意思:
令M为this值,检查Type(M)===Object, 如果不是则直接抛出异常

map.set.call(null, 'key', 10); // TypeError

如果是Object但没有内部插槽,依然抛出异常(很多情况下对象都有自己的internal slot,例如Set)

const proxy = new Proxy(map, {});
proxy.set('test', 1); // TypeError
// 解决方案
const proxy = new Proxy(map, {
  get(target, prop, receiver) {
    // prop为set,获取到 map.set
    const value = Reflect.get(...arguments);
    return typeof value === 'function' ? value.bind(target) : value;
  },
});

后面的操作可以理解为查找,最终检查是否有[[key]],且SameValueZero(p.[[key]],key)

这里说明一下SameValueZero, 首先JS中有SameValue判断,就是Object.is(a,b),基本上大部分判断都是符合直觉的,有一个地方不同:认为+0和-0是不一样的。
Object.is(0,-0) // false
SameValueZero则是和SameValue规则相同的情况下,+0与-0也是一致的比较。map,set中key的比较都使用这种规则。

过去看到实例代码等一直以为has是否比get快得多,都是先用has判断再get来尽可能减少get的调用次数。但得出结论并不是。
因此在写算法中遍历数组或者字符串收集信息存入哈希表等情况时,个人喜欢如下写法1。

for (const item of xxx) {
  const value = (map.get(item) ?? 0) + 1;
  map.set(item, value);
  
  // 过去常看到的写法
  if (map.has(item)) {
  	map.set(item,map.get(item)+1);
  }
}

Map.prototype.has()使用

那么是否根本没有使用has的必要?也不是。
目前发现有特别情况下需要使用:key或value是一个falsy值, 例如就像上面的情况中,使用了??来规避除undefined与null的其他falsy值,但如果key本身就是存在的(例如有一个key 'x'的value是undefined),由于我这个判断我会认为这个x不存在。或者在key是一个falsy值的情况下可能也会导致一些潜在的误判?
因此map.has(key) 可以理解为比较严谨的判断是否真的有此key。
就跟使用'prop' in objectobject['prop'] ,并不能严谨的判断obj是否真的有prop而不是继承的,严谨的方法应该使用Object.prototype.hasOwnProperty(prop)

就到这里吧,只是浅谈,如有不对感谢评论指正!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值