Map.prototype.has()仅判断键是否存在,即使值为undefined也返回true;delete()彻底移除键值对,而set(key, undefined)仍保留键;clear()批量清空性能远优于循环delete()。

Map.prototype.has() 判断键是否存在,但不等于值不为 undefined
很多人误以为 has() 是在检查「这个键对应的值是不是有效」,其实它只关心键本身是否被显式设置过。哪怕你执行过 map.set('k', undefined),has('k') 依然返回 true。
常见错误现象:
用 if (map.get('x') !== undefined) 替代 has('x'),结果漏掉显式存了 undefined 的情况;或者反过来,用 has() 去判断值是否「有业务意义」,导致逻辑错判。
- 判断键是否存在(比如做缓存命中检测),优先用
has() - 判断值是否「非空/有效」(如非
null、非undefined、非空字符串),必须用get()+ 显式比较 -
has()性能略优于get(),因为它不读取值,只查哈希表结构
delete() 删除键后,get() 返回 undefined,但 has() 返回 false
delete() 是唯一能真正从 Map 中移除键值对的操作。它和对象的 delete obj.key 不同——Map 的 delete() 是方法调用,且返回布尔值表示是否删除成功。
使用场景:
需要彻底清理缓存项、释放引用避免内存泄漏、或实现 LRU 等需精确控制键生命周期的逻辑。
-
map.delete('k')成功删除返回true,删不存在的键返回false - 删完再调
get('k')得undefined,has('k')得false,二者行为一致 - 别用
map.set('k', undefined)代替delete():键还在,遍历仍会出现,内存也没释放 - 注意兼容性:
Map.prototype.delete()在 IE 完全不支持,Node.js 0.12+ 起可用
has() 和 delete() 都不能替代 clear() 批量清空
想清空整个 Map?别循环调 delete(),也别靠 has() 判断后跳过——直接上 clear()。
性能影响很实在:
一个含 1000 个键的 Map,循环 delete() 平均比 clear() 慢 3–5 倍(V8 引擎下),因为每次 delete() 都要重新哈希、重平衡,而 clear() 是直接丢弃整个内部哈希表并新建。
-
clear()后,size变 0,所有has()都返回false - 如果只需清空「满足条件」的部分键,再用
for...of配合has()+delete(),但记得先收集要删的键名,避免边遍历边删引发迭代异常 -
clear()不触发任何监听(比如 Proxy 的deleteProperty),这点和手动delete()不同
Map 里存对象作键时,has() 和 delete() 认的是引用,不是内容
这是最容易踩的坑:用普通对象当键,然后换了个新对象去 has() 或 delete(),永远返回 false。
示例:const key = { id: 1 }; map.set(key, 'data');
之后写 map.has({ id: 1 }) → false,因为是另一个对象实例。
- 键比较用的是 SameValueZero 算法,对象只看引用是否相同
- 解决办法只有两个:复用同一个对象实例,或改用字符串等原始值作键(比如
JSON.stringify(obj),但要注意顺序、undefined、函数等会被忽略) - WeakMap 虽然也用对象作键,但它不提供
has()和delete()方法,所以这问题在 WeakMap 里根本不会出现——但也意味着你没法主动查或删
has() 和 delete() 只管键,不管值语义;对象键的引用陷阱,在真实业务里往往到线上才暴露。

















